This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- get_tab_bar_item_kbd
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- pad_mode_line
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- gui_union_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 #include <config.h>
434 #include <stdlib.h>
435 #include <limits.h>
436 #include <math.h>
437
438 #include "lisp.h"
439 #include "atimer.h"
440 #include "composite.h"
441 #include "keyboard.h"
442 #include "sysstdio.h"
443 #include "systime.h"
444 #include "frame.h"
445 #include "window.h"
446 #include "termchar.h"
447 #include "dispextern.h"
448 #include "character.h"
449 #include "category.h"
450 #include "buffer.h"
451 #include "charset.h"
452 #include "indent.h"
453 #include "commands.h"
454 #include "keymap.h"
455 #include "disptab.h"
456 #include "termhooks.h"
457 #include "termopts.h"
458 #include "intervals.h"
459 #include "coding.h"
460 #include "region-cache.h"
461 #include "font.h"
462 #include "fontset.h"
463 #include "blockinput.h"
464 #include "xwidget.h"
465 #ifdef HAVE_WINDOW_SYSTEM
466 #include TERM_HEADER
467 #endif
468
469 #ifndef FRAME_OUTPUT_DATA
470 #define FRAME_OUTPUT_DATA(f) (NULL)
471 #endif
472
473 #define DISP_INFINITY 10000000
474
475
476 static Lisp_Object list_of_error;
477
478 #ifdef HAVE_WINDOW_SYSTEM
479
480
481
482
483 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
484 (!NILP (Voverflow_newline_into_fringe) \
485 && FRAME_WINDOW_P ((IT)->f) \
486 && ((IT)->bidi_it.paragraph_dir == R2L \
487 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
488 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
489 && (IT)->current_x == (IT)->last_visible_x)
490
491 #else
492 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
493 #endif
494
495
496
497
498
499 #define IT_DISPLAYING_WHITESPACE(it) \
500 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
501 || ((STRINGP (it->string) \
502 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
503 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
504 || (it->s \
505 && (it->s[IT_BYTEPOS (*it)] == ' ' \
506 || it->s[IT_BYTEPOS (*it)] == '\t')) \
507 || (IT_BYTEPOS (*it) < ZV_BYTE \
508 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
509 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
510
511
512
513 #define NOT_AT_EOL '<'
514 #define NOT_AT_BOL '>'
515 #define LINE_BREAKABLE '|'
516
517 static bool
518 it_char_has_category(struct it *it, int cat)
519 {
520 int ch = 0;
521 if (it->what == IT_CHARACTER)
522 ch = it->c;
523 else if (STRINGP (it->string))
524 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
525 else if (it->s)
526 ch = it->s[IT_BYTEPOS (*it)];
527 else if (IT_BYTEPOS (*it) < ZV_BYTE)
528 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
529
530 if (ch == 0)
531 return false;
532 else
533 return CHAR_HAS_CATEGORY (ch, cat);
534 }
535
536
537 static bool
538 char_can_wrap_before (struct it *it)
539 {
540 if (!word_wrap_by_category)
541 return !IT_DISPLAYING_WHITESPACE (it);
542
543
544
545
546 int not_at_bol;
547 if (it->glyph_row && it->glyph_row->reversed_p)
548 not_at_bol = NOT_AT_EOL;
549 else
550 not_at_bol = NOT_AT_BOL;
551
552
553 return (!IT_DISPLAYING_WHITESPACE (it)
554
555 && !it_char_has_category (it, not_at_bol));
556 }
557
558
559 static bool
560 char_can_wrap_after (struct it *it)
561 {
562 if (!word_wrap_by_category)
563 return IT_DISPLAYING_WHITESPACE (it);
564
565
566
567
568 int not_at_eol;
569 if (it->glyph_row && it->glyph_row->reversed_p)
570 not_at_eol = NOT_AT_BOL;
571 else
572 not_at_eol = NOT_AT_EOL;
573
574 return (IT_DISPLAYING_WHITESPACE (it)
575
576 || (it_char_has_category (it, LINE_BREAKABLE)
577 && !it_char_has_category (it, not_at_eol)));
578 }
579
580 #undef IT_DISPLAYING_WHITESPACE
581 #undef NOT_AT_EOL
582 #undef NOT_AT_BOL
583 #undef LINE_BREAKABLE
584
585
586
587
588 static int
589 fill_column_indicator_column (struct it *it, int char_width)
590 {
591 if (display_fill_column_indicator
592 && !it->w->pseudo_window_p
593 && it->continuation_lines_width == 0
594 && CHARACTERP (Vdisplay_fill_column_indicator_character))
595 {
596 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
597 ? BVAR (current_buffer, fill_column)
598 : Vdisplay_fill_column_indicator_column);
599
600
601
602 if (RANGED_FIXNUMP (0, col, INT_MAX))
603 {
604 int icol = XFIXNUM (col);
605 if (!ckd_mul (&icol, icol, char_width)
606 && !ckd_add (&icol, icol, it->lnum_pixel_width))
607 return icol;
608 }
609 }
610 return -1;
611 }
612
613
614
615 bool noninteractive_need_newline;
616
617
618
619 static bool message_log_need_newline;
620
621
622
623
624 static Lisp_Object message_dolog_marker1;
625 static Lisp_Object message_dolog_marker2;
626 static Lisp_Object message_dolog_marker3;
627
628
629
630
631
632
633 static struct text_pos this_line_start_pos;
634
635
636
637
638 static struct text_pos this_line_end_pos;
639
640
641
642 static int this_line_vpos;
643 static int this_line_y;
644 static int this_line_pixel_height;
645
646
647
648
649 static int this_line_start_x;
650
651
652
653
654
655 static struct text_pos this_line_min_pos;
656
657
658
659 static struct buffer *this_line_buffer;
660
661
662
663 static bool overlay_arrow_seen;
664
665
666
667 static Lisp_Object default_invis_vector[3];
668
669
670
671
672
673 Lisp_Object echo_area_window;
674
675
676
677
678 static Lisp_Object Vmessage_stack;
679
680
681
682
683 static bool message_enable_multibyte;
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 int windows_or_buffers_changed;
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736 int update_mode_lines;
737
738
739
740
741 static bool line_number_displayed;
742
743
744
745
746 Lisp_Object echo_area_buffer[2];
747
748
749
750 static Lisp_Object echo_buffer[2];
751
752
753
754 static Lisp_Object Vwith_echo_area_save_vector;
755
756
757
758
759 static bool display_last_displayed_message_p;
760
761
762
763
764 static bool message_buf_print;
765
766
767
768
769 static bool message_cleared_p;
770
771
772
773
774 #define MAX_SCRATCH_GLYPHS 100
775 static struct glyph_row scratch_glyph_row;
776 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
777
778
779
780 static int last_height;
781
782
783
784 bool help_echo_showing_p;
785
786
787
788
789
790
791
792 #define TEXT_PROP_DISTANCE_LIMIT 100
793
794
795
796
797
798
799
800
801 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
802 do { \
803 if (CACHE) \
804 bidi_unshelve_cache (CACHE, true); \
805 ITCOPY = ITORIG; \
806 CACHE = bidi_shelve_cache (); \
807 } while (false)
808
809 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
810 do { \
811 if (pITORIG != pITCOPY) \
812 *(pITORIG) = *(pITCOPY); \
813 bidi_unshelve_cache (CACHE, false); \
814 CACHE = NULL; \
815 } while (false)
816
817
818 enum { REDISPLAY_SOME = 2};
819
820 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
821 struct font *, bool, int *);
822
823 void
824 redisplay_other_windows (void)
825 {
826 if (!windows_or_buffers_changed)
827 windows_or_buffers_changed = REDISPLAY_SOME;
828 }
829
830 void
831 wset_redisplay (struct window *w)
832 {
833
834 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
835 redisplay_other_windows ();
836 w->redisplay = true;
837 }
838
839 void
840 fset_redisplay (struct frame *f)
841 {
842 redisplay_other_windows ();
843 f->redisplay = true;
844 }
845
846 void
847 bset_redisplay (struct buffer *b)
848 {
849 int count = buffer_window_count (b);
850 if (count > 0)
851 {
852
853 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
854 redisplay_other_windows ();
855
856
857
858 b->text->redisplay = true;
859 }
860 }
861
862 void
863 bset_update_mode_line (struct buffer *b)
864 {
865 if (!update_mode_lines)
866 update_mode_lines = REDISPLAY_SOME;
867 b->text->redisplay = true;
868 }
869
870 void
871 wset_update_mode_line (struct window *w)
872 {
873 w->update_mode_line = true;
874
875
876
877
878
879
880 wset_redisplay (w);
881 }
882
883 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
884 Sset_buffer_redisplay, 4, 4, 0,
885 doc:
886 )
887 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
888 {
889 bset_update_mode_line (current_buffer);
890 current_buffer->prevent_redisplay_optimizations_p = true;
891 return Qnil;
892 }
893
894
895
896
897
898 #ifdef GLYPH_DEBUG
899 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
900 bool trace_redisplay_p;
901 #else
902 enum { trace_redisplay_p = false };
903 #endif
904 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
905 redisplay_trace (char const *fmt, ...)
906 {
907 if (trace_redisplay_p)
908 {
909 va_list ap;
910 va_start (ap, fmt);
911 vprintf (fmt, ap);
912 va_end (ap);
913 }
914 }
915
916 #ifdef DEBUG_TRACE_MOVE
917 extern bool trace_move EXTERNALLY_VISIBLE;
918 bool trace_move;
919 #else
920 enum { trace_move = false };
921 #endif
922 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
923 move_trace (char const *fmt, ...)
924 {
925 if (trace_move)
926 {
927 va_list ap;
928 va_start (ap, fmt);
929 vprintf (fmt, ap);
930 va_end (ap);
931 }
932 }
933
934
935
936 static struct buffer *displayed_buffer;
937
938
939
940 enum prop_handled
941 {
942 HANDLED_NORMALLY,
943 HANDLED_RECOMPUTE_PROPS,
944 HANDLED_OVERLAY_STRING_CONSUMED,
945 HANDLED_RETURN
946 };
947
948
949
950
951 struct props
952 {
953
954 short name;
955
956
957 enum prop_idx idx;
958
959
960
961 enum prop_handled (*handler) (struct it *it);
962 };
963
964 static enum prop_handled handle_face_prop (struct it *);
965 static enum prop_handled handle_invisible_prop (struct it *);
966 static enum prop_handled handle_display_prop (struct it *);
967 static enum prop_handled handle_composition_prop (struct it *);
968 static enum prop_handled handle_overlay_change (struct it *);
969 static enum prop_handled handle_fontified_prop (struct it *);
970
971
972
973 static struct props it_props[] =
974 {
975 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
976
977
978 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
979 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
980 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
981 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
982 {0, 0, NULL}
983 };
984
985
986
987 enum move_it_result
988 {
989
990 MOVE_UNDEFINED,
991
992
993 MOVE_POS_MATCH_OR_ZV,
994
995
996 MOVE_X_REACHED,
997
998
999
1000 MOVE_LINE_CONTINUED,
1001
1002
1003
1004 MOVE_LINE_TRUNCATED,
1005
1006
1007 MOVE_NEWLINE_OR_CR
1008 };
1009
1010
1011
1012
1013
1014
1015 #define CLEAR_FACE_CACHE_COUNT 500
1016 static int clear_face_cache_count;
1017
1018
1019
1020 #ifdef HAVE_WINDOW_SYSTEM
1021 #define CLEAR_IMAGE_CACHE_COUNT 101
1022 static int clear_image_cache_count;
1023
1024
1025 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1026 #endif
1027
1028
1029
1030 bool redisplaying_p;
1031
1032
1033
1034
1035
1036
1037
1038
1039 bool display_working_on_window_p;
1040
1041
1042
1043
1044 Lisp_Object help_echo_string;
1045 Lisp_Object help_echo_window;
1046 Lisp_Object help_echo_object;
1047 ptrdiff_t help_echo_pos;
1048
1049
1050
1051 Lisp_Object previous_help_echo_string;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056
1057
1058 static bool hourglass_shown_p;
1059
1060
1061
1062 static struct atimer *hourglass_atimer;
1063
1064 #endif
1065
1066
1067
1068 #define DEFAULT_HOURGLASS_DELAY 1
1069
1070 #ifdef HAVE_WINDOW_SYSTEM
1071
1072
1073 #define THIN_SPACE_WIDTH 1
1074
1075 #endif
1076
1077
1078
1079 static void setup_for_ellipsis (struct it *, int);
1080 static void set_iterator_to_next (struct it *, bool);
1081 static void mark_window_display_accurate_1 (struct window *, bool);
1082 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1083 static bool cursor_row_p (struct glyph_row *);
1084 static int redisplay_mode_lines (Lisp_Object, bool);
1085
1086 static void handle_line_prefix (struct it *);
1087
1088 static void handle_stop_backwards (struct it *, ptrdiff_t);
1089 static void unwind_with_echo_area_buffer (Lisp_Object);
1090 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1091 static bool current_message_1 (void *, Lisp_Object);
1092 static bool truncate_message_1 (void *, Lisp_Object);
1093 static void set_message (Lisp_Object);
1094 static bool set_message_1 (void *, Lisp_Object);
1095 static bool display_echo_area_1 (void *, Lisp_Object);
1096 static bool resize_mini_window_1 (void *, Lisp_Object);
1097 static void unwind_redisplay (void);
1098 static void extend_face_to_end_of_line (struct it *);
1099 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1100 static void push_it (struct it *, struct text_pos *);
1101 static void iterate_out_of_display_property (struct it *);
1102 static void pop_it (struct it *);
1103 static void redisplay_internal (void);
1104 static void echo_area_display (bool);
1105 static void block_buffer_flips (void);
1106 static void unblock_buffer_flips (void);
1107 static void redisplay_windows (Lisp_Object);
1108 static void redisplay_window (Lisp_Object, bool);
1109 static Lisp_Object redisplay_window_error (Lisp_Object);
1110 static Lisp_Object redisplay_window_0 (Lisp_Object);
1111 static Lisp_Object redisplay_window_1 (Lisp_Object);
1112 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1113 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1114 int, int);
1115 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1116 static bool update_menu_bar (struct frame *, bool, bool);
1117 static bool try_window_reusing_current_matrix (struct window *);
1118 static int try_window_id (struct window *);
1119 static void maybe_produce_line_number (struct it *);
1120 static bool should_produce_line_number (struct it *);
1121 static bool display_line (struct it *, int);
1122 static int display_mode_lines (struct window *);
1123 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1124 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1125 Lisp_Object, bool);
1126 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1127 Lisp_Object);
1128 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1129 static void display_menu_bar (struct window *);
1130 static void display_tab_bar (struct window *);
1131 static void update_tab_bar (struct frame *, bool);
1132 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1133 ptrdiff_t *);
1134 static void pint2str (register char *, register int, register ptrdiff_t);
1135
1136 static int display_string (const char *, Lisp_Object, Lisp_Object,
1137 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1138 int);
1139 static void compute_line_metrics (struct it *);
1140 static bool get_overlay_strings (struct it *, ptrdiff_t);
1141 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1142 static void next_overlay_string (struct it *);
1143 static void reseat (struct it *, struct text_pos, bool);
1144 static void reseat_1 (struct it *, struct text_pos, bool);
1145 static bool next_element_from_display_vector (struct it *);
1146 static bool next_element_from_string (struct it *);
1147 static bool next_element_from_c_string (struct it *);
1148 static bool next_element_from_buffer (struct it *);
1149 static bool next_element_from_composition (struct it *);
1150 static bool next_element_from_image (struct it *);
1151 static bool next_element_from_stretch (struct it *);
1152 static bool next_element_from_xwidget (struct it *);
1153 static void load_overlay_strings (struct it *, ptrdiff_t);
1154 static bool get_next_display_element (struct it *);
1155 static enum move_it_result
1156 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1157 enum move_operation_enum);
1158 static void get_visually_first_element (struct it *);
1159 static void compute_stop_pos (struct it *);
1160 static int face_before_or_after_it_pos (struct it *, bool);
1161 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1162 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1163 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *,
1165 ptrdiff_t, int, bool, bool);
1166 static int underlying_face_id (const struct it *);
1167
1168 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1169 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1170
1171 #ifdef HAVE_WINDOW_SYSTEM
1172
1173 static void update_tool_bar (struct frame *, bool);
1174 static void gui_draw_bottom_divider (struct window *w);
1175 static void notice_overwritten_cursor (struct window *,
1176 enum glyph_row_area,
1177 int, int, int, int);
1178 static int normal_char_height (struct font *, int);
1179 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1180
1181 static void append_stretch_glyph (struct it *, Lisp_Object,
1182 int, int, int);
1183
1184 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1185 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1186 struct font *, int, bool);
1187 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1188 struct glyph_row *,
1189 struct window *, struct face *,
1190 struct face *);
1191 static void get_cursor_offset_for_mouse_face (struct window *w,
1192 struct glyph_row *row,
1193 int *offset);
1194 #endif
1195
1196 static void produce_special_glyphs (struct it *, enum display_element_type);
1197 static void pad_mode_line (struct it *, bool);
1198 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1199 static bool coords_in_mouse_face_p (struct window *, int, int);
1200 static void reset_box_start_end_flags (struct it *);
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 int
1215 window_text_bottom_y (struct window *w)
1216 {
1217 int height = WINDOW_PIXEL_HEIGHT (w);
1218
1219 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1220
1221 if (window_wants_mode_line (w))
1222 height -= CURRENT_MODE_LINE_HEIGHT (w);
1223
1224 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1225
1226 return height;
1227 }
1228
1229
1230
1231
1232
1233 int
1234 window_box_width (struct window *w, enum glyph_row_area area)
1235 {
1236 int width = w->pixel_width;
1237
1238 if (!w->pseudo_window_p)
1239 {
1240 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1241 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1242
1243 if (area == TEXT_AREA)
1244 width -= (WINDOW_MARGINS_WIDTH (w)
1245 + WINDOW_FRINGES_WIDTH (w));
1246 else if (area == LEFT_MARGIN_AREA)
1247 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1248 else if (area == RIGHT_MARGIN_AREA)
1249 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1250 }
1251
1252
1253
1254 return max (0, width);
1255 }
1256
1257
1258
1259
1260
1261 int
1262 window_box_height (struct window *w)
1263 {
1264 struct frame *f = XFRAME (w->frame);
1265 int height = WINDOW_PIXEL_HEIGHT (w);
1266
1267 eassert (height >= 0);
1268
1269 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1270 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1271
1272
1273
1274
1275
1276
1277
1278 if (window_wants_mode_line (w))
1279 {
1280 if (w->mode_line_height >= 0)
1281 height -= w->mode_line_height;
1282 else
1283 {
1284 struct glyph_row *ml_row
1285 = (w->current_matrix && w->current_matrix->rows
1286 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1287 : 0);
1288 if (ml_row && ml_row->mode_line_p)
1289 height -= ml_row->height;
1290 else
1291 height -= estimate_mode_line_height
1292 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1293 }
1294 }
1295
1296 if (window_wants_tab_line (w))
1297 {
1298 if (w->tab_line_height >= 0)
1299 height -= w->tab_line_height;
1300 else
1301 {
1302 struct glyph_row *tl_row
1303 = (w->current_matrix && w->current_matrix->rows
1304 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1305 : 0);
1306 if (tl_row && tl_row->mode_line_p)
1307 height -= tl_row->height;
1308 else
1309 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1310 }
1311 }
1312
1313 if (window_wants_header_line (w))
1314 {
1315 if (w->header_line_height >= 0)
1316 height -= w->header_line_height;
1317 else
1318 {
1319 struct glyph_row *hl_row
1320 = (w->current_matrix && w->current_matrix->rows
1321 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1322 : 0);
1323 if (hl_row && hl_row->mode_line_p)
1324 height -= hl_row->height;
1325 else
1326 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1327 }
1328 }
1329
1330
1331
1332 return max (0, height);
1333 }
1334
1335
1336
1337
1338
1339 int
1340 window_box_left_offset (struct window *w, enum glyph_row_area area)
1341 {
1342 int x;
1343
1344 if (w->pseudo_window_p)
1345 return 0;
1346
1347 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1348
1349 if (area == TEXT_AREA)
1350 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1351 + window_box_width (w, LEFT_MARGIN_AREA));
1352 else if (area == RIGHT_MARGIN_AREA)
1353 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1354 + window_box_width (w, LEFT_MARGIN_AREA)
1355 + window_box_width (w, TEXT_AREA)
1356 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1357 ? 0
1358 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1359 else if (area == LEFT_MARGIN_AREA
1360 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1361 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1362
1363
1364 return min (x, w->pixel_width);
1365 }
1366
1367
1368
1369
1370
1371
1372 static int
1373 window_box_right_offset (struct window *w, enum glyph_row_area area)
1374 {
1375
1376 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1377 w->pixel_width);
1378 }
1379
1380
1381
1382
1383
1384 int
1385 window_box_left (struct window *w, enum glyph_row_area area)
1386 {
1387 struct frame *f = XFRAME (w->frame);
1388 int x;
1389
1390 if (w->pseudo_window_p)
1391 return FRAME_INTERNAL_BORDER_WIDTH (f);
1392
1393 x = (WINDOW_LEFT_EDGE_X (w)
1394 + window_box_left_offset (w, area));
1395
1396 return x;
1397 }
1398
1399
1400
1401
1402
1403
1404 int
1405 window_box_right (struct window *w, enum glyph_row_area area)
1406 {
1407 return window_box_left (w, area) + window_box_width (w, area);
1408 }
1409
1410
1411
1412
1413
1414
1415
1416
1417 void
1418 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1419 int *box_y, int *box_width, int *box_height)
1420 {
1421 if (box_width)
1422 *box_width = window_box_width (w, area);
1423 if (box_height)
1424 *box_height = window_box_height (w);
1425 if (box_x)
1426 *box_x = window_box_left (w, area);
1427 if (box_y)
1428 {
1429 *box_y = WINDOW_TOP_EDGE_Y (w);
1430 if (window_wants_tab_line (w))
1431 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1432 if (window_wants_header_line (w))
1433 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1434 }
1435 }
1436
1437 #ifdef HAVE_WINDOW_SYSTEM
1438
1439
1440
1441
1442
1443
1444
1445
1446 static void
1447 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1448 int *bottom_right_x, int *bottom_right_y)
1449 {
1450 window_box (w, ANY_AREA, top_left_x, top_left_y,
1451 bottom_right_x, bottom_right_y);
1452 *bottom_right_x += *top_left_x;
1453 *bottom_right_y += *top_left_y;
1454 }
1455
1456 #endif
1457
1458
1459
1460
1461
1462
1463
1464
1465 int
1466 line_bottom_y (struct it *it)
1467 {
1468 int line_height = it->max_ascent + it->max_descent;
1469 int line_top_y = it->current_y;
1470
1471 if (line_height == 0)
1472 {
1473 if (last_height)
1474 line_height = last_height;
1475 else if (IT_CHARPOS (*it) < ZV)
1476 {
1477 move_it_by_lines (it, 1);
1478 line_height = (it->max_ascent || it->max_descent
1479 ? it->max_ascent + it->max_descent
1480 : last_height);
1481 }
1482 else
1483 {
1484 struct glyph_row *row = it->glyph_row;
1485
1486
1487 it->glyph_row = NULL;
1488 it->what = IT_CHARACTER;
1489 it->c = ' ';
1490 it->len = 1;
1491 PRODUCE_GLYPHS (it);
1492 line_height = it->ascent + it->descent;
1493 it->glyph_row = row;
1494 }
1495 }
1496
1497 return line_top_y + line_height;
1498 }
1499
1500 DEFUN ("line-pixel-height", Fline_pixel_height,
1501 Sline_pixel_height, 0, 0, 0,
1502 doc:
1503
1504 )
1505 (void)
1506 {
1507 struct it it;
1508 struct text_pos pt;
1509 struct window *w = XWINDOW (selected_window);
1510 struct buffer *old_buffer = NULL;
1511 Lisp_Object result;
1512
1513 if (XBUFFER (w->contents) != current_buffer)
1514 {
1515 old_buffer = current_buffer;
1516 set_buffer_internal_1 (XBUFFER (w->contents));
1517 }
1518 SET_TEXT_POS (pt, PT, PT_BYTE);
1519 void *itdata = bidi_shelve_cache ();
1520 start_display (&it, w, pt);
1521
1522
1523
1524 move_it_by_lines (&it, 0);
1525 it.vpos = it.current_y = 0;
1526 last_height = 0;
1527 result = make_fixnum (line_bottom_y (&it));
1528 if (old_buffer)
1529 set_buffer_internal_1 (old_buffer);
1530
1531 bidi_unshelve_cache (itdata, false);
1532 return result;
1533 }
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549 int
1550 default_line_pixel_height (struct window *w)
1551 {
1552 struct frame *f = WINDOW_XFRAME (w);
1553 int height = FRAME_LINE_HEIGHT (f);
1554
1555 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1556 {
1557 struct buffer *b = XBUFFER (w->contents);
1558 Lisp_Object val = BVAR (b, extra_line_spacing);
1559
1560 if (NILP (val))
1561 val = BVAR (&buffer_defaults, extra_line_spacing);
1562 if (!NILP (val))
1563 {
1564 if (RANGED_FIXNUMP (0, val, INT_MAX))
1565 height += XFIXNAT (val);
1566 else if (FLOATP (val))
1567 {
1568 int addon = XFLOAT_DATA (val) * height + 0.5;
1569
1570 if (addon >= 0)
1571 height += addon;
1572 }
1573 }
1574 else
1575 height += f->extra_line_spacing;
1576 }
1577
1578 return height;
1579 }
1580
1581
1582
1583 static Lisp_Object
1584 string_from_display_spec (Lisp_Object spec)
1585 {
1586 if (VECTORP (spec))
1587 {
1588 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1589 if (STRINGP (AREF (spec, i)))
1590 return AREF (spec, i);
1591 }
1592 else
1593 {
1594 for (; CONSP (spec); spec = XCDR (spec))
1595 if (STRINGP (XCAR (spec)))
1596 return XCAR (spec);
1597 }
1598 return spec;
1599 }
1600
1601
1602
1603
1604
1605 static int
1606 window_hscroll_limited (struct window *w, struct frame *f)
1607 {
1608 ptrdiff_t window_hscroll = w->hscroll;
1609 int window_text_width = window_box_width (w, TEXT_AREA);
1610 int colwidth = FRAME_COLUMN_WIDTH (f);
1611
1612 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1613 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1614
1615 return window_hscroll;
1616 }
1617
1618
1619
1620
1621
1622 static void
1623 reset_box_start_end_flags (struct it *it)
1624 {
1625
1626
1627 if (it->area == TEXT_AREA
1628
1629 && !(it->what == IT_IMAGE && it->image_id < 0))
1630 {
1631
1632
1633
1634
1635 if (it->face_box_p)
1636 it->start_of_box_run_p = false;
1637 it->end_of_box_run_p = false;
1638 }
1639 }
1640
1641
1642
1643
1644
1645
1646
1647 bool
1648 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1649 int *rtop, int *rbot, int *rowh, int *vpos)
1650 {
1651 struct it it;
1652 void *itdata = bidi_shelve_cache ();
1653 struct text_pos top;
1654 bool visible_p = false;
1655 struct buffer *old_buffer = NULL;
1656 bool r2l = false;
1657
1658 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1659 return visible_p;
1660
1661 if (XBUFFER (w->contents) != current_buffer)
1662 {
1663 old_buffer = current_buffer;
1664 set_buffer_internal_1 (XBUFFER (w->contents));
1665 }
1666
1667 SET_TEXT_POS_FROM_MARKER (top, w->start);
1668
1669
1670
1671
1672 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1673 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1674
1675
1676
1677 if (charpos >= 0 && CHARPOS (top) > charpos)
1678 return visible_p;
1679
1680
1681
1682
1683
1684
1685
1686
1687 int prev_mode_line_height = w->mode_line_height;
1688 int prev_header_line_height = w->header_line_height;
1689 int prev_tab_line_height = w->tab_line_height;
1690
1691 if (window_wants_mode_line (w))
1692 {
1693 Lisp_Object window_mode_line_format
1694 = window_parameter (w, Qmode_line_format);
1695
1696 w->mode_line_height
1697 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1698 NILP (window_mode_line_format)
1699 ? BVAR (current_buffer, mode_line_format)
1700 : window_mode_line_format);
1701 }
1702
1703 if (window_wants_tab_line (w))
1704 {
1705 Lisp_Object window_tab_line_format
1706 = window_parameter (w, Qtab_line_format);
1707
1708 w->tab_line_height
1709 = display_mode_line (w, TAB_LINE_FACE_ID,
1710 NILP (window_tab_line_format)
1711 ? BVAR (current_buffer, tab_line_format)
1712 : window_tab_line_format);
1713 }
1714
1715 if (window_wants_header_line (w))
1716 {
1717 Lisp_Object window_header_line_format
1718 = window_parameter (w, Qheader_line_format);
1719
1720 w->header_line_height
1721 = display_mode_line (w, HEADER_LINE_FACE_ID,
1722 NILP (window_header_line_format)
1723 ? BVAR (current_buffer, header_line_format)
1724 : window_header_line_format);
1725 }
1726
1727 start_display (&it, w, top);
1728 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1729 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1730
1731
1732
1733 if (!NILP (Vdisplay_line_numbers)
1734 && it.current_x >= it.first_visible_x
1735 && IT_CHARPOS (it) == charpos
1736 && !it.line_number_produced_p)
1737 {
1738
1739
1740
1741 if (!it.lnum_pixel_width)
1742 {
1743 struct it it2;
1744 void *it2data = NULL;
1745
1746 SAVE_IT (it2, it, it2data);
1747 move_it_by_lines (&it, 1);
1748 it2.lnum_pixel_width = it.lnum_pixel_width;
1749 RESTORE_IT (&it, &it2, it2data);
1750 }
1751 it.current_x += it.lnum_pixel_width;
1752 }
1753
1754 if (charpos >= 0
1755 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1756 && IT_CHARPOS (it) >= charpos)
1757
1758
1759
1760 || (it.bidi_p && it.bidi_it.scan_dir == -1
1761 && IT_CHARPOS (it) <= charpos)))
1762 {
1763
1764
1765
1766
1767
1768
1769 int top_x = it.current_x;
1770 int top_y = it.current_y;
1771 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1772 int bottom_y;
1773 struct it save_it;
1774 void *save_it_data = NULL;
1775
1776
1777 SAVE_IT (save_it, it, save_it_data);
1778 last_height = 0;
1779 bottom_y = line_bottom_y (&it);
1780 if (top_y < window_top_y)
1781 visible_p = bottom_y > window_top_y;
1782 else if (top_y < it.last_visible_y)
1783 visible_p = true;
1784 if (bottom_y >= it.last_visible_y
1785 && it.bidi_p && it.bidi_it.scan_dir == -1
1786 && IT_CHARPOS (it) < charpos)
1787 {
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798 int ten_more_lines = 10 * default_line_pixel_height (w);
1799
1800 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1801 MOVE_TO_POS | MOVE_TO_Y);
1802 if (it.current_y > top_y)
1803 visible_p = false;
1804
1805 }
1806 RESTORE_IT (&it, &save_it, save_it_data);
1807 if (visible_p)
1808 {
1809 if (it.method == GET_FROM_DISPLAY_VECTOR)
1810 {
1811
1812
1813 if (charpos < 2 || top.charpos >= charpos)
1814 top_x = it.glyph_row->x;
1815 else
1816 {
1817 struct it it2, it2_prev;
1818
1819
1820
1821
1822
1823
1824 start_display (&it2, w, top);
1825 it2.glyph_row = NULL;
1826 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1827
1828
1829
1830
1831 if (IT_CHARPOS (it2) != charpos - 1)
1832 it2_prev = it2;
1833 else
1834 {
1835
1836
1837
1838 do {
1839 get_next_display_element (&it2);
1840 PRODUCE_GLYPHS (&it2);
1841 it2_prev = it2;
1842 set_iterator_to_next (&it2, true);
1843 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1844 && IT_CHARPOS (it2) < charpos);
1845 }
1846 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1847 || it2_prev.current_x > it2_prev.last_visible_x)
1848 top_x = it.glyph_row->x;
1849 else
1850 {
1851 top_x = it2_prev.current_x;
1852 top_y = it2_prev.current_y;
1853 }
1854 }
1855 }
1856 else if (IT_CHARPOS (it) != charpos)
1857 {
1858 Lisp_Object cpos = make_fixnum (charpos);
1859 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1860 Lisp_Object string = string_from_display_spec (spec);
1861 struct text_pos tpos;
1862 bool newline_in_string
1863 = (STRINGP (string)
1864 && memchr (SDATA (string), '\n', SBYTES (string)));
1865
1866 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1867 bool replacing_spec_p
1868 = (!NILP (spec)
1869 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1870 charpos, FRAME_WINDOW_P (it.f)));
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887 if (replacing_spec_p)
1888 {
1889 Lisp_Object startpos, endpos;
1890 EMACS_INT start, end;
1891 struct it it3;
1892
1893
1894
1895 endpos =
1896 Fnext_single_char_property_change (cpos, Qdisplay,
1897 Qnil, Qnil);
1898 startpos =
1899 Fprevious_single_char_property_change (endpos, Qdisplay,
1900 Qnil, Qnil);
1901 start = XFIXNAT (startpos);
1902 end = XFIXNAT (endpos);
1903
1904
1905 start_display (&it3, w, top);
1906 if (start > CHARPOS (top))
1907 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1908
1909
1910
1911
1912 if (it3.method == GET_FROM_BUFFER
1913 && (it3.c == '\n'
1914 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1915 move_it_by_lines (&it3, 1);
1916 else if (move_it_in_display_line_to (&it3, -1,
1917 it3.current_x
1918 + it3.pixel_width,
1919 MOVE_TO_X)
1920 == MOVE_LINE_CONTINUED)
1921 {
1922 move_it_by_lines (&it3, 1);
1923
1924
1925
1926 if (it3.line_wrap == WORD_WRAP)
1927 move_it_by_lines (&it3, -1);
1928 }
1929
1930
1931
1932 top_y = it3.current_y;
1933 if (it3.bidi_p)
1934 {
1935
1936
1937
1938
1939
1940 start_display (&it3, w, top);
1941 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1942 if (it3.current_y < top_y)
1943 top_y = it3.current_y;
1944 }
1945
1946
1947
1948 start_display (&it3, w, top);
1949 it3.glyph_row = NULL;
1950 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1951
1952
1953
1954
1955
1956
1957
1958 bool it3_moved = false;
1959 int top_x_before_string = it3.current_x;
1960
1961
1962
1963
1964
1965 while (get_next_display_element (&it3))
1966 {
1967 if (!EQ (it3.object, string))
1968 top_x_before_string = it3.current_x;
1969 PRODUCE_GLYPHS (&it3);
1970 if ((it3.bidi_it.scan_dir == 1
1971 && IT_CHARPOS (it3) >= charpos)
1972 || (it3.bidi_it.scan_dir == -1
1973 && IT_CHARPOS (it3) <= charpos)
1974 || ITERATOR_AT_END_OF_LINE_P (&it3))
1975 break;
1976 it3_moved = true;
1977 set_iterator_to_next (&it3, false);
1978 }
1979 top_x = it3.current_x - it3.pixel_width;
1980
1981
1982
1983 if (!it3.line_number_produced_p)
1984 {
1985 if (it3.lnum_pixel_width > 0)
1986 {
1987 top_x += it3.lnum_pixel_width;
1988 top_x_before_string += it3.lnum_pixel_width;
1989 }
1990 else if (it.line_number_produced_p)
1991 {
1992 top_x += it.lnum_pixel_width;
1993 top_x_before_string += it3.lnum_pixel_width;
1994 }
1995 }
1996
1997
1998
1999
2000
2001
2002 if (it3_moved
2003 && newline_in_string
2004 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2005 top_x = top_x_before_string;
2006 }
2007 }
2008
2009 *x = top_x;
2010
2011
2012
2013
2014 if (it.ascent == 0 && it.what == IT_IMAGE
2015 && it.method != GET_FROM_IMAGE
2016 && it.image_id < 0
2017 && it.max_ascent > 0)
2018 *y = max (top_y, window_top_y);
2019 else
2020 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2021 *rtop = max (0, window_top_y - top_y);
2022 *rbot = max (0, bottom_y - it.last_visible_y);
2023 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2024 - max (top_y, window_top_y)));
2025 *vpos = it.vpos;
2026 if (it.bidi_it.paragraph_dir == R2L)
2027 r2l = true;
2028 }
2029 }
2030 else
2031 {
2032
2033
2034
2035 struct it it2;
2036 void *it2data = NULL;
2037
2038 SAVE_IT (it2, it, it2data);
2039 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2040 move_it_by_lines (&it, 1);
2041 if (charpos < IT_CHARPOS (it)
2042 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2043 {
2044 visible_p = true;
2045 RESTORE_IT (&it2, &it2, it2data);
2046 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2047 *x = it2.current_x;
2048 if (it2.ascent == 0 && it2.what == IT_IMAGE
2049 && it2.method != GET_FROM_IMAGE
2050 && it2.image_id < 0
2051 && it2.max_ascent > 0)
2052 *y = it2.current_y;
2053 else
2054 *y = it2.current_y + it2.max_ascent - it2.ascent;
2055 *rtop = max (0, -it2.current_y);
2056 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2057 - it.last_visible_y));
2058 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2059 it.last_visible_y)
2060 - max (max (it2.current_y,
2061 WINDOW_TAB_LINE_HEIGHT (w)),
2062 WINDOW_HEADER_LINE_HEIGHT (w))));
2063 *vpos = it2.vpos;
2064 if (it2.bidi_it.paragraph_dir == R2L)
2065 r2l = true;
2066 }
2067 else
2068 bidi_unshelve_cache (it2data, true);
2069 }
2070 bidi_unshelve_cache (itdata, false);
2071
2072 if (old_buffer)
2073 set_buffer_internal_1 (old_buffer);
2074
2075 if (visible_p)
2076 {
2077 if (w->hscroll > 0)
2078 *x -=
2079 window_hscroll_limited (w, WINDOW_XFRAME (w))
2080 * WINDOW_FRAME_COLUMN_WIDTH (w);
2081
2082
2083
2084
2085
2086 if (r2l)
2087 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2088 }
2089
2090 #if false
2091
2092 if (visible_p)
2093 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2094 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2095 else
2096 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2097 #endif
2098
2099
2100 w->mode_line_height = prev_mode_line_height;
2101 w->header_line_height = prev_header_line_height;
2102 w->tab_line_height = prev_tab_line_height;
2103
2104 return visible_p;
2105 }
2106
2107
2108
2109
2110
2111
2112
2113 static int
2114 check_char_and_length (const unsigned char *str, int *len)
2115 {
2116 int c = string_char_and_length (str, len);
2117 if (!CHAR_VALID_P (c))
2118
2119
2120
2121 c = '?';
2122
2123 return c;
2124 }
2125
2126
2127
2128
2129
2130
2131 static struct text_pos
2132 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2133 {
2134 eassert (STRINGP (string) && nchars >= 0);
2135
2136 if (STRING_MULTIBYTE (string))
2137 {
2138 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2139
2140 while (nchars--)
2141 {
2142 int len = BYTES_BY_CHAR_HEAD (*p);
2143 p += len;
2144 CHARPOS (pos) += 1;
2145 BYTEPOS (pos) += len;
2146 }
2147 }
2148 else
2149 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2150
2151 return pos;
2152 }
2153
2154
2155
2156
2157
2158 static struct text_pos
2159 string_pos (ptrdiff_t charpos, Lisp_Object string)
2160 {
2161 struct text_pos pos;
2162 eassert (STRINGP (string));
2163 eassert (charpos >= 0);
2164 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2165 return pos;
2166 }
2167
2168
2169
2170
2171
2172
2173 static struct text_pos
2174 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2175 {
2176 struct text_pos pos;
2177
2178 eassert (s != NULL);
2179 eassert (charpos >= 0);
2180
2181 if (multibyte_p)
2182 {
2183 SET_TEXT_POS (pos, 0, 0);
2184 while (charpos--)
2185 {
2186 int len = BYTES_BY_CHAR_HEAD (*s);
2187 s += len;
2188 CHARPOS (pos) += 1;
2189 BYTEPOS (pos) += len;
2190 }
2191 }
2192 else
2193 SET_TEXT_POS (pos, charpos, charpos);
2194
2195 return pos;
2196 }
2197
2198
2199
2200
2201
2202 static ptrdiff_t
2203 number_of_chars (const char *s, bool multibyte_p)
2204 {
2205 ptrdiff_t nchars;
2206
2207 if (multibyte_p)
2208 {
2209 ptrdiff_t rest = strlen (s);
2210 const unsigned char *p = (const unsigned char *) s;
2211
2212 for (nchars = 0; rest > 0; ++nchars)
2213 {
2214 int len = BYTES_BY_CHAR_HEAD (*p);
2215 rest -= len, p += len;
2216 }
2217 }
2218 else
2219 nchars = strlen (s);
2220
2221 return nchars;
2222 }
2223
2224
2225
2226
2227
2228
2229 static void
2230 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2231 {
2232 eassert (STRINGP (string));
2233 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2234
2235 if (STRING_MULTIBYTE (string))
2236 *newpos = string_pos_nchars_ahead (pos, string,
2237 CHARPOS (*newpos) - CHARPOS (pos));
2238 else
2239 BYTEPOS (*newpos) = CHARPOS (*newpos);
2240 }
2241
2242
2243
2244
2245
2246 int
2247 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2248 {
2249 #ifdef HAVE_WINDOW_SYSTEM
2250 if (FRAME_WINDOW_P (f))
2251 {
2252 int height = FONT_HEIGHT (FRAME_FONT (f));
2253
2254
2255
2256 if (FRAME_FACE_CACHE (f))
2257 {
2258 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2259 if (face)
2260 {
2261 if (face->font)
2262 height = normal_char_height (face->font, -1);
2263 if (face->box_horizontal_line_width > 0)
2264 height += 2 * face->box_horizontal_line_width;
2265 }
2266 }
2267
2268 return height;
2269 }
2270 #endif
2271
2272 return 1;
2273 }
2274
2275
2276
2277
2278
2279
2280 void
2281 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2282 NativeRectangle *bounds, bool noclip)
2283 {
2284
2285 #ifdef HAVE_WINDOW_SYSTEM
2286 if (FRAME_WINDOW_P (f))
2287 {
2288
2289
2290 if (pix_x < 0)
2291 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2292 if (pix_y < 0)
2293 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2294
2295 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2296 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2297
2298 if (bounds)
2299 STORE_NATIVE_RECT (*bounds,
2300 FRAME_COL_TO_PIXEL_X (f, pix_x),
2301 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2302 FRAME_COLUMN_WIDTH (f) - 1,
2303 FRAME_LINE_HEIGHT (f) - 1);
2304
2305
2306 if (!noclip)
2307 {
2308 if (pix_x < 0)
2309 pix_x = 0;
2310 else if (pix_x > FRAME_TOTAL_COLS (f))
2311 pix_x = FRAME_TOTAL_COLS (f);
2312
2313 if (pix_y < 0)
2314 pix_y = 0;
2315 else if (pix_y > FRAME_TOTAL_LINES (f))
2316 pix_y = FRAME_TOTAL_LINES (f);
2317 }
2318 }
2319 #endif
2320
2321 *x = pix_x;
2322 *y = pix_y;
2323 }
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334 struct glyph *
2335 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2336 int *dx, int *dy, int *area)
2337 {
2338 struct glyph *glyph, *end;
2339 struct glyph_row *row = NULL;
2340 int x0, i;
2341
2342
2343 for (i = 0; i < w->current_matrix->nrows; ++i)
2344 {
2345 row = MATRIX_ROW (w->current_matrix, i);
2346 if (!row->enabled_p)
2347 return NULL;
2348 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2349 break;
2350 }
2351
2352 *vpos = i;
2353 *hpos = 0;
2354
2355
2356 if (i == w->current_matrix->nrows)
2357 return NULL;
2358
2359
2360 if (w->pseudo_window_p)
2361 {
2362 *area = TEXT_AREA;
2363 x0 = 0;
2364 }
2365 else
2366 {
2367 if (x < window_box_left_offset (w, TEXT_AREA))
2368 {
2369 *area = LEFT_MARGIN_AREA;
2370 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2371 }
2372 else if (x < window_box_right_offset (w, TEXT_AREA))
2373 {
2374 *area = TEXT_AREA;
2375 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2376 }
2377 else
2378 {
2379 *area = RIGHT_MARGIN_AREA;
2380 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2381 }
2382 }
2383
2384
2385 glyph = row->glyphs[*area];
2386 end = glyph + row->used[*area];
2387 x -= x0;
2388 while (glyph < end && x >= glyph->pixel_width)
2389 {
2390 x -= glyph->pixel_width;
2391 ++glyph;
2392 }
2393
2394 if (glyph == end)
2395 return NULL;
2396
2397 if (dx)
2398 {
2399 *dx = x;
2400 *dy = y - (row->y + row->ascent - glyph->ascent);
2401 }
2402
2403 *hpos = glyph - row->glyphs[*area];
2404 return glyph;
2405 }
2406
2407
2408
2409
2410 static void
2411 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2412 {
2413 if (w->pseudo_window_p)
2414 {
2415
2416
2417 struct frame *f = XFRAME (w->frame);
2418 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2419 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2420 }
2421 else
2422 {
2423 *x -= WINDOW_LEFT_EDGE_X (w);
2424 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2425 }
2426 }
2427
2428 #ifdef HAVE_WINDOW_SYSTEM
2429
2430
2431
2432
2433
2434 int
2435 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2436 {
2437 Emacs_Rectangle r;
2438
2439 if (n <= 0)
2440 return 0;
2441
2442 if (s->row->full_width_p)
2443 {
2444
2445 r.x = WINDOW_LEFT_EDGE_X (s->w);
2446 if (s->row->mode_line_p)
2447 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2448 else
2449 r.width = WINDOW_PIXEL_WIDTH (s->w);
2450
2451
2452
2453 if (s->w->pseudo_window_p)
2454 r.height = s->row->visible_height;
2455 else
2456 r.height = s->height;
2457 }
2458 else
2459 {
2460
2461 r.x = window_box_left (s->w, s->area);
2462 r.width = window_box_width (s->w, s->area);
2463 r.height = s->row->visible_height;
2464 }
2465
2466 if (s->clip_head)
2467 if (r.x < s->clip_head->x)
2468 {
2469 if (r.width >= s->clip_head->x - r.x)
2470 r.width -= s->clip_head->x - r.x;
2471 else
2472 r.width = 0;
2473 r.x = s->clip_head->x;
2474 }
2475 if (s->clip_tail)
2476 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2477 {
2478 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2479 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2480 else
2481 r.width = 0;
2482 }
2483
2484
2485
2486
2487 if (s->for_overlaps)
2488 {
2489 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2490 r.height = window_text_bottom_y (s->w) - r.y;
2491
2492
2493
2494
2495
2496
2497 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2498 {
2499 Emacs_Rectangle rc, r_save = r;
2500
2501 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2502 rc.y = s->w->phys_cursor.y;
2503 rc.width = s->w->phys_cursor_width;
2504 rc.height = s->w->phys_cursor_height;
2505
2506 gui_intersect_rectangles (&r_save, &rc, &r);
2507 }
2508 }
2509 else
2510 {
2511
2512
2513
2514 if (!s->row->full_width_p
2515 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2516 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2517 else
2518 r.y = max (0, s->row->y);
2519 }
2520
2521 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2522
2523
2524
2525 if (s->hl == DRAW_CURSOR)
2526 {
2527 struct glyph *glyph = s->first_glyph;
2528 int height, max_y;
2529
2530 if (s->x > r.x)
2531 {
2532 if (r.width >= s->x - r.x)
2533 r.width -= s->x - r.x;
2534 else
2535 r.width = 0;
2536 r.x = s->x;
2537 }
2538 r.width = min (r.width, glyph->pixel_width);
2539
2540
2541 height = min (glyph->ascent + glyph->descent,
2542 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2543 max_y = window_text_bottom_y (s->w) - height;
2544 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2545 if (s->ybase - glyph->ascent > max_y)
2546 {
2547 r.y = max_y;
2548 r.height = height;
2549 }
2550 else
2551 {
2552
2553 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2554 if (height < r.height)
2555 {
2556 max_y = r.y + r.height;
2557 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2558 r.height = min (max_y - r.y, height);
2559 }
2560 }
2561 }
2562
2563 if (s->row->clip)
2564 {
2565 Emacs_Rectangle r_save = r;
2566
2567 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2568 r.width = 0;
2569 }
2570
2571 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2572 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2573 {
2574 #ifdef CONVERT_FROM_EMACS_RECT
2575 CONVERT_FROM_EMACS_RECT (r, *rects);
2576 #else
2577 *rects = r;
2578 #endif
2579 return 1;
2580 }
2581 else
2582 {
2583
2584
2585
2586
2587 #ifdef CONVERT_FROM_EMACS_RECT
2588 Emacs_Rectangle rs[2];
2589 #else
2590 Emacs_Rectangle *rs = rects;
2591 #endif
2592 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2593
2594 if (s->for_overlaps & OVERLAPS_PRED)
2595 {
2596 rs[i] = r;
2597 if (r.y + r.height > row_y)
2598 {
2599 if (r.y < row_y)
2600 rs[i].height = row_y - r.y;
2601 else
2602 rs[i].height = 0;
2603 }
2604 i++;
2605 }
2606 if (s->for_overlaps & OVERLAPS_SUCC)
2607 {
2608 rs[i] = r;
2609 if (r.y < row_y + s->row->visible_height)
2610 {
2611 if (r.y + r.height > row_y + s->row->visible_height)
2612 {
2613 rs[i].y = row_y + s->row->visible_height;
2614 rs[i].height = r.y + r.height - rs[i].y;
2615 }
2616 else
2617 rs[i].height = 0;
2618 }
2619 i++;
2620 }
2621
2622 n = i;
2623 #ifdef CONVERT_FROM_EMACS_RECT
2624 for (i = 0; i < n; i++)
2625 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2626 #endif
2627 return n;
2628 }
2629 }
2630
2631
2632
2633
2634 void
2635 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2636 {
2637 get_glyph_string_clip_rects (s, nr, 1);
2638 }
2639
2640
2641
2642
2643
2644
2645
2646 void
2647 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2648 struct glyph *glyph, int *xp, int *yp, int *heightp)
2649 {
2650 struct frame *f = XFRAME (WINDOW_FRAME (w));
2651 int x, y, wd, h, h0, y0, ascent;
2652
2653
2654
2655
2656
2657 wd = glyph->pixel_width;
2658
2659 x = w->phys_cursor.x;
2660 if (x < 0)
2661 {
2662 wd += x;
2663 x = 0;
2664 }
2665
2666 if (glyph->type == STRETCH_GLYPH
2667 && !x_stretch_cursor_p)
2668 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2669 w->phys_cursor_width = wd;
2670
2671
2672
2673 y = w->phys_cursor.y;
2674 ascent = row->ascent;
2675
2676
2677
2678 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2679 {
2680 y -= glyph->ascent - row->ascent;
2681 ascent = glyph->ascent;
2682 }
2683
2684
2685 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2686
2687 h = max (h0, ascent + glyph->descent);
2688
2689
2690 h = min (h, row->height);
2691 h0 = min (h0, ascent + glyph->descent);
2692
2693 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2694 if (y < y0)
2695 {
2696 h = max (h - (y0 - y) + 1, h0);
2697 y = y0 - 1;
2698 }
2699 else
2700 {
2701 y0 = window_text_bottom_y (w) - h0;
2702 if (y > y0)
2703 {
2704 h += y - y0;
2705 y = y0;
2706 }
2707 }
2708
2709 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2710 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2711 *heightp = h;
2712 }
2713
2714
2715
2716
2717
2718 void
2719 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2720 {
2721 Lisp_Object window;
2722 struct window *w;
2723 struct glyph_row *r, *gr, *end_row;
2724 enum window_part part;
2725 enum glyph_row_area area;
2726 int x, y, width, height;
2727
2728 if (mouse_fine_grained_tracking)
2729 {
2730 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2731 return;
2732 }
2733
2734
2735
2736
2737 if (window_resize_pixelwise)
2738 {
2739 width = height = 1;
2740 goto virtual_glyph;
2741 }
2742 else if (!f->glyphs_initialized_p
2743 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2744 NILP (window)))
2745 {
2746 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2747 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2748 goto virtual_glyph;
2749 }
2750
2751 w = XWINDOW (window);
2752 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2753 height = WINDOW_FRAME_LINE_HEIGHT (w);
2754
2755 x = window_relative_x_coord (w, part, gx);
2756 y = gy - WINDOW_TOP_EDGE_Y (w);
2757
2758 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2759 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2760
2761 if (w->pseudo_window_p)
2762 {
2763 area = TEXT_AREA;
2764 part = ON_MODE_LINE;
2765 goto text_glyph;
2766 }
2767
2768 switch (part)
2769 {
2770 case ON_LEFT_MARGIN:
2771 area = LEFT_MARGIN_AREA;
2772 goto text_glyph;
2773
2774 case ON_RIGHT_MARGIN:
2775 area = RIGHT_MARGIN_AREA;
2776 goto text_glyph;
2777
2778 case ON_TAB_LINE:
2779 case ON_HEADER_LINE:
2780 case ON_MODE_LINE:
2781 gr = (part == ON_TAB_LINE
2782 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2783 : (part == ON_HEADER_LINE
2784 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2785 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2786 gy = gr->y;
2787 area = TEXT_AREA;
2788 goto text_glyph_row_found;
2789
2790 case ON_TEXT:
2791 area = TEXT_AREA;
2792
2793 text_glyph:
2794 gr = 0; gy = 0;
2795 for (; r <= end_row && r->enabled_p; ++r)
2796 if (r->y + r->height > y)
2797 {
2798 gr = r; gy = r->y;
2799 break;
2800 }
2801
2802 text_glyph_row_found:
2803 if (gr && gy <= y)
2804 {
2805 struct glyph *g = gr->glyphs[area];
2806 struct glyph *end = g + gr->used[area];
2807
2808 height = gr->height;
2809 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2810 if (gx + g->pixel_width > x)
2811 break;
2812
2813 if (g < end)
2814 {
2815 if (g->type == IMAGE_GLYPH)
2816 {
2817
2818
2819 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2820 return;
2821 }
2822 width = g->pixel_width;
2823 }
2824 else
2825 {
2826
2827 x -= gx;
2828 gx += (x / width) * width;
2829 }
2830
2831 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2832 && part != ON_TAB_LINE)
2833 {
2834 gx += window_box_left_offset (w, area);
2835
2836
2837 height = min (height,
2838 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2839 }
2840 }
2841 else
2842 {
2843
2844 gx = (x / width) * width;
2845 y -= gy;
2846 gy += (y / height) * height;
2847 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2848 && part != ON_TAB_LINE)
2849
2850 height = min (height,
2851 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2852 }
2853 break;
2854
2855 case ON_LEFT_FRINGE:
2856 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2857 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2858 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2859 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2860 goto row_glyph;
2861
2862 case ON_RIGHT_FRINGE:
2863 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2864 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2865 : window_box_right_offset (w, TEXT_AREA));
2866 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2867 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2868 && !WINDOW_RIGHTMOST_P (w))
2869 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2870
2871
2872 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2873 else
2874 width = WINDOW_PIXEL_WIDTH (w) - gx;
2875 else
2876 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2877
2878 goto row_glyph;
2879
2880 case ON_VERTICAL_BORDER:
2881 gx = WINDOW_PIXEL_WIDTH (w) - width;
2882 goto row_glyph;
2883
2884 case ON_VERTICAL_SCROLL_BAR:
2885 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2886 ? 0
2887 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2888 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2889 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2890 : 0)));
2891 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2892
2893 row_glyph:
2894 gr = 0, gy = 0;
2895 for (; r <= end_row && r->enabled_p; ++r)
2896 if (r->y + r->height > y)
2897 {
2898 gr = r; gy = r->y;
2899 break;
2900 }
2901
2902 if (gr && gy <= y)
2903 height = gr->height;
2904 else
2905 {
2906
2907 y -= gy;
2908 gy += (y / height) * height;
2909 }
2910 break;
2911
2912 case ON_RIGHT_DIVIDER:
2913 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2914 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2915 gy = 0;
2916
2917 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2918 goto add_edge;
2919
2920 case ON_BOTTOM_DIVIDER:
2921 gx = 0;
2922 width = WINDOW_PIXEL_WIDTH (w);
2923 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2924 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2925 goto add_edge;
2926
2927 default:
2928 ;
2929 virtual_glyph:
2930
2931
2932
2933
2934
2935
2936 if (gx < 0)
2937 gx -= width - 1;
2938 if (gy < 0)
2939 gy -= height - 1;
2940
2941 gx = (gx / width) * width;
2942 gy = (gy / height) * height;
2943
2944 goto store_rect;
2945 }
2946
2947 add_edge:
2948 gx += WINDOW_LEFT_EDGE_X (w);
2949 gy += WINDOW_TOP_EDGE_Y (w);
2950
2951 store_rect:
2952 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2953
2954
2955 #if false && defined HAVE_X_WINDOWS
2956 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2957 f->output_data.x->normal_gc,
2958 gx, gy, width, height);
2959 #endif
2960 }
2961
2962
2963 #endif
2964
2965 static void
2966 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2967 {
2968 eassert (w);
2969 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
2970 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
2971 w->window_end_vpos
2972 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2973 }
2974
2975 static bool
2976 hscrolling_current_line_p (struct window *w)
2977 {
2978 return (!w->suspend_auto_hscroll
2979 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2980 Qcurrent_line));
2981 }
2982
2983
2984
2985
2986
2987
2988
2989 static Lisp_Object
2990 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
2991 {
2992 add_to_log ("Error during redisplay: %S signaled %S",
2993 Flist (nargs, args), arg);
2994 return Qnil;
2995 }
2996
2997
2998
2999
3000
3001 static Lisp_Object
3002 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3003 {
3004 Lisp_Object val;
3005
3006 if (inhibit_eval_during_redisplay)
3007 val = Qnil;
3008 else
3009 {
3010 ptrdiff_t i;
3011 specpdl_ref count = SPECPDL_INDEX ();
3012 Lisp_Object *args;
3013 USE_SAFE_ALLOCA;
3014 SAFE_ALLOCA_LISP (args, nargs);
3015
3016 args[0] = func;
3017 for (i = 1; i < nargs; i++)
3018 args[i] = va_arg (ap, Lisp_Object);
3019
3020 specbind (Qinhibit_redisplay, Qt);
3021 if (inhibit_quit)
3022 specbind (Qinhibit_quit, Qt);
3023
3024
3025 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3026 safe_eval_handler);
3027 val = SAFE_FREE_UNBIND_TO (count, val);
3028 }
3029
3030 return val;
3031 }
3032
3033 Lisp_Object
3034 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3035 {
3036 Lisp_Object retval;
3037 va_list ap;
3038
3039 va_start (ap, func);
3040 retval = safe__call (false, nargs, func, ap);
3041 va_end (ap);
3042 return retval;
3043 }
3044
3045
3046
3047
3048 Lisp_Object
3049 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3050 {
3051 return safe_call (2, fn, arg);
3052 }
3053
3054 static Lisp_Object
3055 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3056 {
3057 Lisp_Object retval;
3058 va_list ap;
3059
3060 va_start (ap, fn);
3061 retval = safe__call (inhibit_quit, 2, fn, ap);
3062 va_end (ap);
3063 return retval;
3064 }
3065
3066 Lisp_Object
3067 safe_eval (Lisp_Object sexpr)
3068 {
3069 return safe__call1 (false, Qeval, sexpr);
3070 }
3071
3072 static Lisp_Object
3073 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3074 {
3075 return safe__call1 (inhibit_quit, Qeval, sexpr);
3076 }
3077
3078
3079
3080
3081 Lisp_Object
3082 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3083 {
3084 return safe_call (3, fn, arg1, arg2);
3085 }
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096 static void
3097 CHECK_IT (struct it *it)
3098 {
3099 #if false
3100 if (it->method == GET_FROM_STRING)
3101 {
3102 eassert (STRINGP (it->string));
3103 eassert (IT_STRING_CHARPOS (*it) >= 0);
3104 }
3105 else
3106 {
3107 eassert (IT_STRING_CHARPOS (*it) < 0);
3108 if (it->method == GET_FROM_BUFFER)
3109 {
3110
3111 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3112 }
3113 }
3114
3115 if (it->dpvec)
3116 eassert (it->current.dpvec_index >= 0);
3117 else
3118 eassert (it->current.dpvec_index < 0);
3119 #endif
3120 }
3121
3122
3123
3124
3125
3126 static void
3127 CHECK_WINDOW_END (struct window *w)
3128 {
3129 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3130 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3131 {
3132 struct glyph_row *row;
3133 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3134 !row->enabled_p
3135 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3136 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3137 }
3138 #endif
3139 }
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164 void
3165 init_iterator (struct it *it, struct window *w,
3166 ptrdiff_t charpos, ptrdiff_t bytepos,
3167 struct glyph_row *row, enum face_id base_face_id)
3168 {
3169 enum face_id remapped_base_face_id = base_face_id;
3170 int body_width = 0, body_height = 0;
3171
3172
3173 eassert (w != NULL && it != NULL);
3174 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3175 && charpos <= ZV));
3176
3177
3178
3179
3180
3181 if (!inhibit_free_realized_faces)
3182 {
3183 if (face_change)
3184 {
3185 face_change = false;
3186 XFRAME (w->frame)->face_change = 0;
3187 free_all_realized_faces (Qnil);
3188 }
3189 else if (XFRAME (w->frame)->face_change)
3190 {
3191 XFRAME (w->frame)->face_change = 0;
3192 free_all_realized_faces (w->frame);
3193 }
3194 }
3195
3196
3197 if (! NILP (Vface_remapping_alist))
3198 remapped_base_face_id
3199 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3200
3201
3202
3203 if (row == NULL)
3204 {
3205 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3206 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3207 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3208 else if (base_face_id == TAB_LINE_FACE_ID)
3209 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3210 else if (base_face_id == HEADER_LINE_FACE_ID)
3211 {
3212
3213 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3214 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3215 }
3216 }
3217
3218
3219
3220 memclear (it, sizeof *it);
3221 it->current.overlay_string_index = -1;
3222 it->current.dpvec_index = -1;
3223 it->base_face_id = remapped_base_face_id;
3224 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3225 it->paragraph_embedding = L2R;
3226 it->bidi_it.w = w;
3227
3228
3229 XSETWINDOW (it->window, w);
3230 it->w = w;
3231 it->f = XFRAME (w->frame);
3232
3233 it->cmp_it.id = -1;
3234 it->cmp_it.parent_it = it;
3235
3236 if (max_redisplay_ticks > 0)
3237 update_redisplay_ticks (0, w);
3238
3239
3240 if (base_face_id == DEFAULT_FACE_ID
3241 && FRAME_WINDOW_P (it->f))
3242 {
3243 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3244 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3245 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3246 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3247 * FRAME_LINE_HEIGHT (it->f));
3248 else if (it->f->extra_line_spacing > 0)
3249 it->extra_line_spacing = it->f->extra_line_spacing;
3250 }
3251
3252
3253
3254
3255
3256 if (FRAME_FACE_CACHE (it->f) == NULL)
3257 init_frame_faces (it->f);
3258 if (FRAME_FACE_CACHE (it->f)->used == 0)
3259 recompute_basic_faces (it->f);
3260
3261 it->override_ascent = -1;
3262
3263
3264 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3265
3266
3267
3268
3269 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3270 ? (clip_to_bounds
3271 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3272 PTRDIFF_MAX))
3273 : (!NILP (BVAR (current_buffer, selective_display))
3274 ? -1 : 0));
3275 it->selective_display_ellipsis_p
3276 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3277
3278
3279 it->dp = window_display_table (w);
3280
3281
3282 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3283
3284 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3285
3286
3287 if (TRUNCATE != 0)
3288 it->line_wrap = TRUNCATE;
3289 if (base_face_id == DEFAULT_FACE_ID
3290 && !it->w->hscroll
3291 && (WINDOW_FULL_WIDTH_P (it->w)
3292 || NILP (Vtruncate_partial_width_windows)
3293 || (FIXNUMP (Vtruncate_partial_width_windows)
3294
3295 && (XFIXNUM (Vtruncate_partial_width_windows)
3296 <= WINDOW_TOTAL_COLS (it->w))))
3297 && NILP (BVAR (current_buffer, truncate_lines)))
3298 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3299 ? WINDOW_WRAP : WORD_WRAP;
3300
3301
3302
3303
3304
3305
3306
3307 #ifdef HAVE_WINDOW_SYSTEM
3308 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3309 #endif
3310 {
3311 if (it->line_wrap == TRUNCATE)
3312 {
3313
3314 eassert (it->glyph_row == NULL);
3315 produce_special_glyphs (it, IT_TRUNCATION);
3316 it->truncation_pixel_width = it->pixel_width;
3317 }
3318 else
3319 {
3320
3321 eassert (it->glyph_row == NULL);
3322 produce_special_glyphs (it, IT_CONTINUATION);
3323 it->continuation_pixel_width = it->pixel_width;
3324 }
3325 }
3326
3327
3328
3329 it->pixel_width = it->ascent = it->descent = 0;
3330 it->phys_ascent = it->phys_descent = 0;
3331
3332
3333
3334
3335 it->glyph_row = row;
3336 it->area = TEXT_AREA;
3337
3338
3339
3340
3341
3342 if (base_face_id != DEFAULT_FACE_ID)
3343 {
3344
3345 it->first_visible_x = 0;
3346 it->last_visible_x =
3347 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3348 }
3349 else
3350 {
3351
3352
3353
3354
3355
3356
3357 if (hscrolling_current_line_p (w))
3358 {
3359 if (w->min_hscroll > 0)
3360 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3361 else
3362 it->first_visible_x = 0;
3363 }
3364 else
3365 it->first_visible_x =
3366 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3367
3368 body_width = window_box_width (w, TEXT_AREA);
3369 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3370 && body_width != w->old_body_pixel_width)
3371 FRAME_WINDOW_CHANGE (it->f) = true;
3372 it->last_visible_x = it->first_visible_x + body_width;
3373
3374
3375
3376
3377 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3378 {
3379 if (it->line_wrap == TRUNCATE)
3380 it->last_visible_x -= it->truncation_pixel_width;
3381 else
3382 it->last_visible_x -= it->continuation_pixel_width;
3383 }
3384
3385 it->tab_line_p = window_wants_tab_line (w);
3386 it->header_line_p = window_wants_header_line (w);
3387 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3388 it->current_y = body_height + w->vscroll;
3389 }
3390
3391
3392 if (!FRAME_WINDOW_P (it->f)
3393 && !WINDOW_RIGHTMOST_P (it->w))
3394 it->last_visible_x -= 1;
3395
3396 it->last_visible_y = window_text_bottom_y (w);
3397 body_height += it->last_visible_y;
3398 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3399 && body_height != w->old_body_pixel_height)
3400 FRAME_WINDOW_CHANGE (it->f) = true;
3401
3402
3403
3404 if (base_face_id != DEFAULT_FACE_ID)
3405 {
3406 struct face *face;
3407
3408 it->face_id = remapped_base_face_id;
3409
3410
3411
3412 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3413 if (face && face->box != FACE_NO_BOX)
3414 {
3415 int box_thickness = face->box_vertical_line_width;
3416 it->face_box_p = true;
3417 it->start_of_box_run_p = true;
3418
3419
3420 if (box_thickness > 0)
3421 it->last_visible_x -= box_thickness;
3422 }
3423 }
3424
3425
3426
3427 if (charpos >= BUF_BEG (current_buffer))
3428 {
3429 it->stop_charpos = charpos;
3430 it->end_charpos = ZV;
3431 eassert (charpos == BYTE_TO_CHAR (bytepos));
3432 IT_CHARPOS (*it) = charpos;
3433 IT_BYTEPOS (*it) = bytepos;
3434
3435
3436
3437 it->face_id = it->base_face_id;
3438
3439 it->start = it->current;
3440
3441
3442
3443
3444
3445
3446
3447 it->bidi_p =
3448 !redisplay__inhibit_bidi
3449 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3450 && it->multibyte_p;
3451
3452
3453
3454 if (it->bidi_p)
3455 {
3456
3457
3458
3459
3460 if (base_face_id == DEFAULT_FACE_ID
3461 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3462 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3463 {
3464 if (it->line_wrap == TRUNCATE)
3465 it->last_visible_x -= it->truncation_pixel_width;
3466 else
3467 it->last_visible_x -= it->continuation_pixel_width;
3468 }
3469
3470
3471 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3472 Qleft_to_right))
3473 it->paragraph_embedding = L2R;
3474 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3475 Qright_to_left))
3476 it->paragraph_embedding = R2L;
3477 else
3478 it->paragraph_embedding = NEUTRAL_DIR;
3479 bidi_unshelve_cache (NULL, false);
3480 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3481 &it->bidi_it);
3482 }
3483
3484
3485
3486 it->medium_narrowing_begv = 0;
3487
3488
3489 reseat (it, it->current.pos, true);
3490 }
3491
3492 CHECK_IT (it);
3493 }
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581 static int
3582 get_narrowed_width (struct window *w)
3583 {
3584
3585
3586 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3587
3588
3589
3590 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3591 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3592 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3593 return fact * max (1, width);
3594 }
3595
3596 static int
3597 get_narrowed_len (struct window *w)
3598 {
3599 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3600 return get_narrowed_width (w) * max (1, height);
3601 }
3602
3603 static ptrdiff_t
3604 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3605 {
3606 int len = get_narrowed_len (w);
3607 return max ((pos / len - 1) * len, BEGV);
3608 }
3609
3610 static ptrdiff_t
3611 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3612 {
3613 int len = get_narrowed_len (w);
3614 return min ((pos / len + 1) * len, ZV);
3615 }
3616
3617
3618
3619
3620
3621
3622 static ptrdiff_t
3623 get_nearby_bol_pos (ptrdiff_t pos)
3624 {
3625 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3626 int dist;
3627 for (dist = 500; dist <= 500000; dist *= 10)
3628 {
3629 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3630 start = pos - dist < BEGV ? BEGV : pos - dist;
3631 for (cur = start; cur < pos; cur = next)
3632 {
3633 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3634 pos, pos_bytepos,
3635 1, &found, NULL, false);
3636 if (found)
3637 bol = next;
3638 else
3639 break;
3640 }
3641 if (bol >= BEGV || start == BEGV)
3642 break;
3643 else
3644 pos = pos - dist < BEGV ? BEGV : pos - dist;
3645 }
3646 eassert (bol <= init_pos);
3647 return bol;
3648 }
3649
3650 ptrdiff_t
3651 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3652 {
3653 int len = get_narrowed_width (w);
3654 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3655 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3656 }
3657
3658 ptrdiff_t
3659 get_large_narrowing_begv (ptrdiff_t pos)
3660 {
3661 if (long_line_optimizations_region_size <= 0)
3662 return BEGV;
3663 int len = long_line_optimizations_region_size / 2;
3664 int begv = max (pos - len, BEGV);
3665 int limit = long_line_optimizations_bol_search_limit;
3666 while (limit > 0)
3667 {
3668 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3669 return begv;
3670 begv--;
3671 limit--;
3672 }
3673 return begv;
3674 }
3675
3676 ptrdiff_t
3677 get_large_narrowing_zv (ptrdiff_t pos)
3678 {
3679 if (long_line_optimizations_region_size <= 0)
3680 return ZV;
3681 int len = long_line_optimizations_region_size / 2;
3682 return min (pos + len, ZV);
3683 }
3684
3685 static void
3686 unwind_narrowed_begv (Lisp_Object point_min)
3687 {
3688 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3689 }
3690
3691
3692
3693
3694 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3695 do { \
3696 if (IT->medium_narrowing_begv) \
3697 { \
3698 specpdl_ref count = SPECPDL_INDEX (); \
3699 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3700 SET_BUF_BEGV (current_buffer, BV); \
3701 DST = EXPR; \
3702 unbind_to (count, Qnil); \
3703 } \
3704 else \
3705 DST = EXPR; \
3706 } while (0)
3707
3708
3709
3710 void
3711 start_display (struct it *it, struct window *w, struct text_pos pos)
3712 {
3713 struct glyph_row *row;
3714 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3715
3716 row = w->desired_matrix->rows + first_vpos;
3717 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3718 it->first_vpos = first_vpos;
3719
3720
3721
3722 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3723 {
3724 int first_y = it->current_y;
3725
3726
3727
3728 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3729 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3730 if (!start_at_line_beg_p)
3731 {
3732 int new_x;
3733
3734 reseat_at_previous_visible_line_start (it);
3735 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3736
3737 new_x = it->current_x + it->pixel_width;
3738
3739
3740
3741
3742
3743
3744
3745 if (it->current_x > 0
3746 && it->line_wrap != TRUNCATE
3747 && (
3748 new_x > it->last_visible_x
3749
3750
3751 || (new_x == it->last_visible_x
3752 && FRAME_WINDOW_P (it->f)
3753 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3754 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3755 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3756 {
3757 if ((it->current.dpvec_index >= 0
3758 || it->current.overlay_string_index >= 0)
3759
3760
3761
3762
3763
3764 && it->c != '\n')
3765 {
3766 set_iterator_to_next (it, true);
3767 move_it_in_display_line_to (it, -1, -1, 0);
3768 }
3769
3770 it->continuation_lines_width += it->current_x;
3771 }
3772
3773
3774
3775
3776
3777 else if (it->current.dpvec_index >= 0)
3778 it->current.dpvec_index = 0;
3779
3780
3781
3782
3783 it->max_ascent = it->max_descent = 0;
3784 it->max_phys_ascent = it->max_phys_descent = 0;
3785
3786 it->current_y = first_y;
3787 it->vpos = 0;
3788 it->current_x = it->hpos = 0;
3789 }
3790 }
3791 }
3792
3793
3794
3795
3796
3797 static bool
3798 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3799 {
3800 Lisp_Object prop, window;
3801 bool ellipses_p = false;
3802 ptrdiff_t charpos = CHARPOS (pos->pos);
3803
3804
3805
3806
3807
3808 if (pos->dpvec_index >= 0
3809 && pos->overlay_string_index < 0
3810 && CHARPOS (pos->string_pos) < 0
3811 && charpos > BEGV
3812 && (XSETWINDOW (window, w),
3813 prop = Fget_char_property (make_fixnum (charpos),
3814 Qinvisible, window),
3815 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3816 {
3817 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3818 window);
3819 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3820 }
3821
3822 return ellipses_p;
3823 }
3824
3825
3826
3827
3828
3829
3830
3831 static bool
3832 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3833 {
3834 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3835 int i;
3836 bool overlay_strings_with_newlines = false;
3837
3838
3839
3840
3841
3842 if (in_ellipses_for_invisible_text_p (pos, w))
3843 {
3844 --charpos;
3845 bytepos = 0;
3846 }
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3858
3859
3860
3861
3862 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3863 {
3864 const char *s = SSDATA (it->overlay_strings[i]);
3865 const char *e = s + SBYTES (it->overlay_strings[i]);
3866
3867 while (s < e && *s != '\n')
3868 ++s;
3869
3870 if (s < e)
3871 {
3872 overlay_strings_with_newlines = true;
3873 break;
3874 }
3875 }
3876
3877
3878
3879 if (pos->overlay_string_index >= 0)
3880 {
3881 int relative_index;
3882
3883
3884
3885
3886
3887 if (it->method == GET_FROM_IMAGE)
3888 pop_it (it);
3889
3890
3891
3892
3893 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3894 {
3895 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3896 it->current.overlay_string_index = 0;
3897 while (n--)
3898 {
3899 load_overlay_strings (it, 0);
3900 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3901 }
3902 }
3903
3904 it->current.overlay_string_index = pos->overlay_string_index;
3905 relative_index = (it->current.overlay_string_index
3906 % OVERLAY_STRING_CHUNK_SIZE);
3907 it->string = it->overlay_strings[relative_index];
3908 eassert (STRINGP (it->string));
3909 it->current.string_pos = pos->string_pos;
3910 it->method = GET_FROM_STRING;
3911 it->end_charpos = SCHARS (it->string);
3912
3913 if (it->bidi_p)
3914 {
3915 it->bidi_it.string.lstring = it->string;
3916 it->bidi_it.string.s = NULL;
3917 it->bidi_it.string.schars = SCHARS (it->string);
3918 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3919 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3920 it->bidi_it.string.unibyte = !it->multibyte_p;
3921 it->bidi_it.w = it->w;
3922 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3923 FRAME_WINDOW_P (it->f), &it->bidi_it);
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933 if (CHARPOS (pos->string_pos) == 0)
3934 {
3935 get_visually_first_element (it);
3936 if (IT_STRING_CHARPOS (*it) != 0)
3937 do {
3938
3939 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3940 bidi_move_to_visually_next (&it->bidi_it);
3941 } while (it->bidi_it.charpos != 0);
3942 }
3943 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3944 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3945 }
3946 }
3947
3948 if (CHARPOS (pos->string_pos) >= 0)
3949 {
3950
3951
3952
3953 it->current.string_pos = pos->string_pos;
3954 eassert (STRINGP (it->string));
3955 if (it->bidi_p)
3956 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3957 FRAME_WINDOW_P (it->f), &it->bidi_it);
3958 }
3959
3960
3961
3962 if (pos->dpvec_index >= 0)
3963 {
3964 if (it->dpvec == NULL)
3965 get_next_display_element (it);
3966 eassert (it->dpvec && it->current.dpvec_index == 0);
3967 it->current.dpvec_index = pos->dpvec_index;
3968 }
3969
3970 CHECK_IT (it);
3971 return !overlay_strings_with_newlines;
3972 }
3973
3974
3975
3976
3977
3978 static void
3979 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
3980 {
3981 init_from_display_pos (it, w, &row->start);
3982 it->start = row->start;
3983 it->continuation_lines_width = row->continuation_lines_width;
3984 CHECK_IT (it);
3985 }
3986
3987
3988
3989
3990
3991
3992
3993
3994 static bool
3995 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
3996 {
3997 bool success = false;
3998
3999 if (init_from_display_pos (it, w, &row->end))
4000 {
4001 if (row->continued_p)
4002 it->continuation_lines_width
4003 = row->continuation_lines_width + row->pixel_width;
4004 CHECK_IT (it);
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014 if (get_next_display_element (it)
4015 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4016 success = false;
4017 else
4018 success = true;
4019 }
4020
4021 return success;
4022 }
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035 static void
4036 handle_stop (struct it *it)
4037 {
4038 enum prop_handled handled;
4039 bool handle_overlay_change_p;
4040 struct props *p;
4041
4042 it->dpvec = NULL;
4043 it->current.dpvec_index = -1;
4044 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4045 it->ellipsis_p = false;
4046
4047
4048 if (it->selective_display_ellipsis_p)
4049 it->saved_face_id = it->face_id;
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093 do
4094 {
4095 handled = HANDLED_NORMALLY;
4096
4097
4098 for (p = it_props; p->handler; ++p)
4099 {
4100 handled = p->handler (it);
4101
4102 if (handled == HANDLED_RECOMPUTE_PROPS)
4103 break;
4104 else if (handled == HANDLED_RETURN)
4105 {
4106
4107
4108 if (!handle_overlay_change_p
4109 || it->sp > 1
4110
4111
4112
4113
4114
4115
4116 || (it->current.overlay_string_index < 0
4117 && !get_overlay_strings_1 (it, 0, false)))
4118 {
4119 if (it->ellipsis_p)
4120 setup_for_ellipsis (it, 0);
4121
4122
4123
4124
4125
4126 if (STRINGP (it->string) && !SCHARS (it->string))
4127 pop_it (it);
4128 return;
4129 }
4130 else if (STRINGP (it->string) && !SCHARS (it->string))
4131 pop_it (it);
4132 else
4133 {
4134 it->string_from_display_prop_p = false;
4135 it->from_disp_prop_p = false;
4136 handle_overlay_change_p = false;
4137 }
4138 handled = HANDLED_RECOMPUTE_PROPS;
4139 break;
4140 }
4141 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4142 handle_overlay_change_p = false;
4143 }
4144
4145 if (handled != HANDLED_RECOMPUTE_PROPS)
4146 {
4147
4148
4149 if (it->method == GET_FROM_DISPLAY_VECTOR)
4150 handle_overlay_change_p = false;
4151
4152
4153
4154
4155 if (handle_overlay_change_p)
4156 handled = handle_overlay_change (it);
4157 }
4158
4159 if (it->ellipsis_p)
4160 {
4161 setup_for_ellipsis (it, 0);
4162 break;
4163 }
4164 }
4165 while (handled == HANDLED_RECOMPUTE_PROPS);
4166
4167
4168 if (handled == HANDLED_NORMALLY)
4169 compute_stop_pos (it);
4170 }
4171
4172
4173
4174
4175
4176 static void
4177 compute_stop_pos (struct it *it)
4178 {
4179 register INTERVAL iv, next_iv;
4180 Lisp_Object object, limit, position;
4181 ptrdiff_t charpos, bytepos, cmp_limit_pos = -1;
4182
4183 if (STRINGP (it->string))
4184 {
4185
4186
4187 it->stop_charpos = it->end_charpos;
4188 object = it->string;
4189 limit = Qnil;
4190 charpos = IT_STRING_CHARPOS (*it);
4191 bytepos = IT_STRING_BYTEPOS (*it);
4192 }
4193 else
4194 {
4195 ptrdiff_t pos;
4196
4197
4198
4199 if (it->end_charpos > ZV)
4200 it->end_charpos = ZV;
4201 it->stop_charpos = it->end_charpos;
4202
4203
4204
4205
4206
4207 charpos = IT_CHARPOS (*it);
4208 bytepos = IT_BYTEPOS (*it);
4209 pos = next_overlay_change (charpos);
4210 if (pos < it->stop_charpos)
4211 it->stop_charpos = pos;
4212
4213 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4214 && !NILP (Vauto_composition_mode)
4215 && composition_break_at_point
4216 && charpos < PT && PT < it->stop_charpos)
4217 it->stop_charpos = PT;
4218
4219
4220
4221 XSETBUFFER (object, current_buffer);
4222 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4223
4224
4225
4226
4227
4228
4229 if (!composition_break_at_point
4230 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4231 && !NILP (Vauto_composition_mode))
4232 {
4233 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4234 bool found = false;
4235
4236 if (pos > ZV)
4237 pos = ZV;
4238 if (endpos > ZV)
4239 endpos = ZV;
4240 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4241 while (pos < endpos)
4242 {
4243 int ch = fetch_char_advance_no_check (&pos, &bpos);
4244 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4245 {
4246 found = true;
4247 break;
4248 }
4249 }
4250 if (found)
4251 {
4252 pos--;
4253 cmp_limit_pos = pos;
4254 }
4255 else if (it->stop_charpos < endpos)
4256 pos = it->stop_charpos;
4257 else
4258 {
4259
4260 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4261 }
4262 }
4263 limit = make_fixnum (pos);
4264 }
4265
4266
4267
4268 position = make_fixnum (charpos);
4269 iv = validate_interval_range (object, &position, &position, false);
4270 if (iv)
4271 {
4272 Lisp_Object values_here[LAST_PROP_IDX];
4273 struct props *p;
4274
4275
4276 for (p = it_props; p->handler; ++p)
4277 values_here[p->idx] = textget (iv->plist,
4278 builtin_lisp_symbol (p->name));
4279
4280
4281
4282 for (next_iv = next_interval (iv);
4283 (next_iv
4284 && (NILP (limit)
4285 || XFIXNAT (limit) > next_iv->position));
4286 next_iv = next_interval (next_iv))
4287 {
4288 for (p = it_props; p->handler; ++p)
4289 {
4290 Lisp_Object new_value = textget (next_iv->plist,
4291 builtin_lisp_symbol (p->name));
4292 if (!EQ (values_here[p->idx], new_value))
4293 break;
4294 }
4295
4296 if (p->handler)
4297 break;
4298 }
4299
4300 if (next_iv)
4301 {
4302 if (FIXNUMP (limit)
4303 && next_iv->position >= XFIXNAT (limit))
4304
4305 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4306 else
4307
4308 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4309 }
4310 }
4311
4312 if (it->cmp_it.id < 0
4313 && (STRINGP (it->string)
4314 || ((!it->bidi_p || it->bidi_it.scan_dir >= 0)
4315 && it->cmp_it.stop_pos <= IT_CHARPOS (*it))))
4316 {
4317 ptrdiff_t stoppos = it->end_charpos;
4318
4319
4320
4321
4322 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4323 stoppos = -1;
4324 else if (cmp_limit_pos > 0)
4325 stoppos = cmp_limit_pos;
4326
4327
4328
4329 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4330 stoppos, it->string, false);
4331 }
4332
4333 eassert (STRINGP (it->string)
4334 || (it->stop_charpos >= BEGV
4335 && it->stop_charpos >= IT_CHARPOS (*it)));
4336 }
4337
4338
4339
4340
4341 #define MAX_DISP_SCAN 250
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355 ptrdiff_t
4356 compute_display_string_pos (struct text_pos *position,
4357 struct bidi_string_data *string,
4358 struct window *w,
4359 bool frame_window_p, int *disp_prop)
4360 {
4361
4362 Lisp_Object object, object1;
4363 Lisp_Object pos, spec, limpos;
4364 bool string_p = string && (STRINGP (string->lstring) || string->s);
4365 ptrdiff_t eob = string_p ? string->schars : ZV;
4366 ptrdiff_t begb = string_p ? 0 : BEGV;
4367 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4368 ptrdiff_t lim =
4369 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4370 struct text_pos tpos;
4371 int rv = 0;
4372
4373 if (string && STRINGP (string->lstring))
4374 object1 = object = string->lstring;
4375 else if (w && !string_p)
4376 {
4377 XSETWINDOW (object, w);
4378 object1 = Qnil;
4379 }
4380 else
4381 object1 = object = Qnil;
4382
4383 *disp_prop = 1;
4384
4385 if (charpos >= eob
4386
4387
4388 || string->from_disp_str
4389
4390 || (string->s && !STRINGP (object)))
4391 {
4392 *disp_prop = 0;
4393 return eob;
4394 }
4395
4396
4397
4398 pos = make_fixnum (charpos);
4399 if (STRINGP (object))
4400 bufpos = string->bufpos;
4401 else
4402 bufpos = charpos;
4403 tpos = *position;
4404 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4405 && (charpos <= begb
4406 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4407 object),
4408 spec))
4409 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4410 frame_window_p)))
4411 {
4412 if (rv == 2)
4413 *disp_prop = 2;
4414 return charpos;
4415 }
4416
4417
4418
4419 limpos = make_fixnum (lim);
4420 do {
4421 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4422 CHARPOS (tpos) = XFIXNAT (pos);
4423 if (CHARPOS (tpos) >= lim)
4424 {
4425 *disp_prop = 0;
4426 break;
4427 }
4428 if (STRINGP (object))
4429 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4430 else
4431 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4432 spec = Fget_char_property (pos, Qdisplay, object);
4433 if (!STRINGP (object))
4434 bufpos = CHARPOS (tpos);
4435 } while (NILP (spec)
4436 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4437 bufpos, frame_window_p)));
4438 if (rv == 2)
4439 *disp_prop = 2;
4440
4441 return CHARPOS (tpos);
4442 }
4443
4444
4445
4446
4447
4448
4449 ptrdiff_t
4450 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4451 {
4452
4453 Lisp_Object object =
4454 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4455 Lisp_Object pos = make_fixnum (charpos);
4456 ptrdiff_t eob =
4457 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4458
4459 if (charpos >= eob || (string->s && !STRINGP (object)))
4460 return eob;
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4477 return -1;
4478
4479
4480
4481 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4482
4483 return XFIXNAT (pos);
4484 }
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496 static enum prop_handled
4497 handle_fontified_prop (struct it *it)
4498 {
4499 Lisp_Object prop, pos;
4500 enum prop_handled handled = HANDLED_NORMALLY;
4501
4502 if (!NILP (Vmemory_full))
4503 return handled;
4504
4505
4506
4507
4508
4509 if (!STRINGP (it->string)
4510 && it->s == NULL
4511 && !NILP (Vfontification_functions)
4512 && !(input_was_pending && redisplay_skip_fontification_on_input)
4513 && !NILP (Vrun_hooks)
4514 && (pos = make_fixnum (IT_CHARPOS (*it)),
4515 prop = Fget_char_property (pos, Qfontified, Qnil),
4516
4517
4518 NILP (prop) && IT_CHARPOS (*it) < Z))
4519 {
4520 specpdl_ref count = SPECPDL_INDEX ();
4521 Lisp_Object val;
4522 struct buffer *obuf = current_buffer;
4523 ptrdiff_t begv = BEGV, zv = ZV;
4524 bool old_clip_changed = current_buffer->clip_changed;
4525 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4526
4527 val = Vfontification_functions;
4528 specbind (Qfontification_functions, Qnil);
4529
4530 eassert (it->end_charpos == ZV);
4531
4532 if (current_buffer->long_line_optimizations_p
4533 && long_line_optimizations_region_size > 0)
4534 {
4535 ptrdiff_t begv = it->large_narrowing_begv;
4536 ptrdiff_t zv = it->large_narrowing_zv;
4537 ptrdiff_t charpos = IT_CHARPOS (*it);
4538 if (charpos < begv || charpos > zv)
4539 {
4540 begv = get_large_narrowing_begv (charpos);
4541 zv = get_large_narrowing_zv (charpos);
4542 }
4543 if (begv != BEG || zv != Z)
4544 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4545 Qlong_line_optimizations_in_fontification_functions);
4546 }
4547
4548
4549
4550 it->f->inhibit_clear_image_cache = true;
4551
4552 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4553 safe_call1 (val, pos);
4554 else
4555 {
4556 Lisp_Object fns, fn;
4557
4558 fns = Qnil;
4559
4560 for (; CONSP (val); val = XCDR (val))
4561 {
4562 fn = XCAR (val);
4563
4564 if (EQ (fn, Qt))
4565 {
4566
4567
4568
4569
4570
4571 for (fns = Fdefault_value (Qfontification_functions);
4572 CONSP (fns);
4573 fns = XCDR (fns))
4574 {
4575 fn = XCAR (fns);
4576 if (!EQ (fn, Qt))
4577 safe_call1 (fn, pos);
4578 }
4579 }
4580 else
4581 safe_call1 (fn, pos);
4582 }
4583 }
4584
4585 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4586 unbind_to (count, Qnil);
4587
4588
4589
4590
4591
4592
4593
4594
4595 if (obuf == current_buffer)
4596 {
4597 if (begv == BEGV && zv == ZV)
4598 current_buffer->clip_changed = old_clip_changed;
4599 }
4600
4601
4602 else if (BUFFER_LIVE_P (obuf))
4603 set_buffer_internal_1 (obuf);
4604
4605
4606
4607
4608
4609
4610 it->end_charpos = ZV;
4611
4612
4613
4614
4615 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4616 handled = HANDLED_RECOMPUTE_PROPS;
4617 }
4618
4619 return handled;
4620 }
4621
4622
4623
4624
4625
4626
4627
4628 static int
4629 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4630 {
4631 ptrdiff_t next_stop;
4632
4633 if (!STRINGP (it->string))
4634 {
4635 return face_at_buffer_position (it->w,
4636 IT_CHARPOS (*it),
4637 &next_stop,
4638 (IT_CHARPOS (*it)
4639 + TEXT_PROP_DISTANCE_LIMIT),
4640 false, it->base_face_id,
4641 attr_filter);
4642 }
4643 else
4644 {
4645 int base_face_id;
4646 ptrdiff_t bufpos;
4647 int i;
4648 Lisp_Object from_overlay
4649 = (it->current.overlay_string_index >= 0
4650 ? it->string_overlays[it->current.overlay_string_index
4651 % OVERLAY_STRING_CHUNK_SIZE]
4652 : Qnil);
4653
4654
4655
4656
4657
4658
4659
4660 if (! NILP (from_overlay))
4661 for (i = it->sp - 1; i >= 0; i--)
4662 {
4663 if (it->stack[i].current.overlay_string_index >= 0)
4664 from_overlay
4665 = it->string_overlays[it->stack[i].current.overlay_string_index
4666 % OVERLAY_STRING_CHUNK_SIZE];
4667 else if (! NILP (it->stack[i].from_overlay))
4668 from_overlay = it->stack[i].from_overlay;
4669
4670 if (!NILP (from_overlay))
4671 break;
4672 }
4673
4674 if (! NILP (from_overlay))
4675 {
4676 bufpos = IT_CHARPOS (*it);
4677
4678
4679 base_face_id
4680 = face_for_overlay_string (it->w,
4681 IT_CHARPOS (*it),
4682 &next_stop,
4683 (IT_CHARPOS (*it)
4684 + TEXT_PROP_DISTANCE_LIMIT),
4685 false,
4686 from_overlay, attr_filter);
4687 }
4688 else
4689 {
4690 bufpos = 0;
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708 base_face_id = it->string_from_prefix_prop_p
4709 ? (!NILP (Vface_remapping_alist)
4710 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4711 : DEFAULT_FACE_ID)
4712 : underlying_face_id (it);
4713 }
4714
4715 return face_at_string_position (it->w,
4716 it->string,
4717 IT_STRING_CHARPOS (*it),
4718 bufpos,
4719 &next_stop,
4720 base_face_id, false,
4721 attr_filter);
4722 }
4723 }
4724
4725
4726
4727
4728 static enum prop_handled
4729 handle_face_prop (struct it *it)
4730 {
4731 specpdl_ref count = SPECPDL_INDEX ();
4732
4733
4734
4735 specbind (Qinhibit_quit, Qt);
4736 const int new_face_id = face_at_pos (it, 0);
4737 unbind_to (count, Qnil);
4738
4739
4740
4741
4742
4743
4744
4745
4746 if (new_face_id != it->face_id)
4747 {
4748 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4749
4750
4751
4752 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4753
4754
4755
4756
4757 if (!STRINGP (it->string)
4758 && !old_face
4759 && IT_CHARPOS (*it) > BEG)
4760 {
4761 const int prev_face_id = face_before_it_pos (it);
4762
4763 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4764 }
4765
4766
4767
4768
4769 it->face_id = new_face_id;
4770
4771
4772 if (!(it->start_of_box_run_p && old_face && old_face->box))
4773 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4774 && (old_face == NULL || !old_face->box));
4775 it->face_box_p = new_face->box != FACE_NO_BOX;
4776 }
4777
4778 return HANDLED_NORMALLY;
4779 }
4780
4781
4782
4783
4784
4785
4786
4787 static int
4788 underlying_face_id (const struct it *it)
4789 {
4790 int face_id = it->base_face_id, i;
4791
4792 eassert (STRINGP (it->string));
4793
4794 for (i = it->sp - 1; i >= 0; --i)
4795 if (NILP (it->stack[i].string))
4796 face_id = it->stack[i].face_id;
4797
4798 return face_id;
4799 }
4800
4801
4802
4803
4804
4805
4806
4807 static int
4808 face_before_or_after_it_pos (struct it *it, bool before_p)
4809 {
4810 int face_id, limit;
4811 ptrdiff_t next_check_charpos;
4812 struct it it_copy;
4813 void *it_copy_data = NULL;
4814
4815 eassert (it->s == NULL);
4816
4817 if (STRINGP (it->string))
4818 {
4819 ptrdiff_t bufpos, charpos;
4820 int base_face_id;
4821
4822
4823
4824
4825
4826 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4827 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4828 || it->current_x <= it->first_visible_x)
4829 return it->face_id;
4830
4831 if (!it->bidi_p)
4832 {
4833
4834
4835
4836 if (before_p)
4837 charpos = IT_STRING_CHARPOS (*it) - 1;
4838 else if (it->what == IT_COMPOSITION)
4839
4840
4841 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4842 else
4843 charpos = IT_STRING_CHARPOS (*it) + 1;
4844 }
4845 else
4846 {
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857 SAVE_IT (it_copy, *it, it_copy_data);
4858 IT_STRING_CHARPOS (it_copy) = 0;
4859 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4860 it_copy.bidi_it.scan_dir = 0;
4861
4862 do
4863 {
4864 charpos = it_copy.bidi_it.charpos;
4865 if (charpos >= SCHARS (it->string))
4866 break;
4867 bidi_move_to_visually_next (&it_copy.bidi_it);
4868 }
4869 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4870
4871 if (!before_p)
4872 {
4873
4874
4875
4876 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4877
4878
4879
4880 if (it_copy.bidi_it.first_elt)
4881 n++;
4882 while (n--)
4883 bidi_move_to_visually_next (&it_copy.bidi_it);
4884
4885 charpos = it_copy.bidi_it.charpos;
4886 }
4887
4888 RESTORE_IT (it, it, it_copy_data);
4889 }
4890 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4891
4892 if (it->current.overlay_string_index >= 0)
4893 bufpos = IT_CHARPOS (*it);
4894 else
4895 bufpos = 0;
4896
4897 base_face_id = underlying_face_id (it);
4898
4899
4900 face_id = face_at_string_position (it->w, it->string, charpos,
4901 bufpos, &next_check_charpos,
4902 base_face_id, false, 0);
4903
4904
4905
4906
4907 if (STRING_MULTIBYTE (it->string))
4908 {
4909 struct text_pos pos1 = string_pos (charpos, it->string);
4910 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4911 struct face *face = FACE_FROM_ID (it->f, face_id);
4912 int len, c = check_char_and_length (p, &len);
4913 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4914 }
4915 }
4916 else
4917 {
4918 struct text_pos pos;
4919
4920 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4921 || (IT_CHARPOS (*it) <= BEGV && before_p))
4922 return it->face_id;
4923
4924 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4925 pos = it->current.pos;
4926
4927 if (!it->bidi_p)
4928 {
4929 if (before_p)
4930 DEC_TEXT_POS (pos, it->multibyte_p);
4931 else
4932 {
4933 if (it->what == IT_COMPOSITION)
4934 {
4935
4936
4937 pos.charpos += it->cmp_it.nchars;
4938 pos.bytepos += it->len;
4939 }
4940 else
4941 INC_TEXT_POS (pos, it->multibyte_p);
4942 }
4943 }
4944 else
4945 {
4946 if (before_p)
4947 {
4948 int current_x;
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959 if (it->current_x <= it->first_visible_x)
4960 return it->face_id;
4961 SAVE_IT (it_copy, *it, it_copy_data);
4962
4963
4964
4965
4966
4967 current_x = it_copy.current_x;
4968 move_it_vertically_backward (&it_copy, 0);
4969 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4970 pos = it_copy.current.pos;
4971 RESTORE_IT (it, it, it_copy_data);
4972 }
4973 else
4974 {
4975
4976
4977
4978 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4979
4980 it_copy = *it;
4981
4982
4983
4984 if (it->bidi_it.first_elt)
4985 n++;
4986 while (n--)
4987 bidi_move_to_visually_next (&it_copy.bidi_it);
4988
4989 SET_TEXT_POS (pos,
4990 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
4991 }
4992 }
4993 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
4994
4995
4996 face_id = face_at_buffer_position (it->w,
4997 CHARPOS (pos),
4998 &next_check_charpos,
4999 limit, false, -1, 0);
5000
5001
5002
5003
5004 if (it->multibyte_p)
5005 {
5006 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
5007 struct face *face = FACE_FROM_ID (it->f, face_id);
5008 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
5009 }
5010 }
5011
5012 return face_id;
5013 }
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024 static enum prop_handled
5025 handle_invisible_prop (struct it *it)
5026 {
5027 enum prop_handled handled = HANDLED_NORMALLY;
5028 int invis;
5029 Lisp_Object prop;
5030
5031 if (STRINGP (it->string))
5032 {
5033 Lisp_Object end_charpos, limit;
5034
5035
5036
5037
5038 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5039 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5040 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5041
5042 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5043 {
5044
5045
5046 bool display_ellipsis_p = (invis == 2);
5047 ptrdiff_t len, endpos;
5048
5049 handled = HANDLED_RECOMPUTE_PROPS;
5050
5051
5052
5053 endpos = len = SCHARS (it->string);
5054 XSETINT (limit, len);
5055 do
5056 {
5057 end_charpos
5058 = Fnext_single_property_change (end_charpos, Qinvisible,
5059 it->string, limit);
5060
5061
5062 eassert (FIXNUMP (end_charpos));
5063 if (FIXNUMP (end_charpos))
5064 {
5065 endpos = XFIXNAT (end_charpos);
5066 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5067 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5068 if (invis == 2)
5069 display_ellipsis_p = true;
5070 }
5071 else
5072 endpos = len;
5073 }
5074 while (invis != 0 && endpos < len);
5075
5076 if (display_ellipsis_p)
5077 it->ellipsis_p = true;
5078
5079 if (endpos < len)
5080 {
5081
5082 struct text_pos old;
5083 ptrdiff_t oldpos;
5084
5085 old = it->current.string_pos;
5086 oldpos = CHARPOS (old);
5087 if (it->bidi_p)
5088 {
5089 if (it->bidi_it.first_elt
5090 && it->bidi_it.charpos < SCHARS (it->string))
5091 bidi_paragraph_init (it->paragraph_embedding,
5092 &it->bidi_it, true);
5093
5094 do
5095 {
5096 bidi_move_to_visually_next (&it->bidi_it);
5097 }
5098 while (oldpos <= it->bidi_it.charpos
5099 && it->bidi_it.charpos < endpos
5100 && it->bidi_it.charpos < it->bidi_it.string.schars);
5101
5102 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5103 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5104 if (IT_CHARPOS (*it) >= endpos)
5105 it->prev_stop = endpos;
5106 }
5107 else
5108 {
5109 IT_STRING_CHARPOS (*it) = endpos;
5110 compute_string_pos (&it->current.string_pos, old, it->string);
5111 }
5112 }
5113 else
5114 {
5115
5116
5117
5118 if (it->current.overlay_string_index >= 0
5119 && !display_ellipsis_p)
5120 {
5121 next_overlay_string (it);
5122
5123
5124 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5125 }
5126 else
5127 {
5128 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5129 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5130 }
5131 }
5132 }
5133 }
5134 else
5135 {
5136 ptrdiff_t newpos, next_stop, start_charpos, tem;
5137 Lisp_Object pos, overlay;
5138
5139
5140 tem = start_charpos = IT_CHARPOS (*it);
5141 pos = make_fixnum (tem);
5142 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5143 &overlay);
5144 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5145
5146
5147 if (invis != 0 && start_charpos < it->end_charpos)
5148 {
5149
5150
5151 bool display_ellipsis_p = invis == 2;
5152
5153 handled = HANDLED_RECOMPUTE_PROPS;
5154
5155
5156
5157 do
5158 {
5159
5160
5161
5162
5163
5164 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5165
5166
5167
5168
5169 if (newpos == tem || newpos >= ZV)
5170 invis = 0;
5171 else
5172 {
5173
5174
5175
5176
5177
5178
5179 pos = make_fixnum (newpos);
5180 prop = Fget_char_property (pos, Qinvisible, it->window);
5181 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5182 }
5183
5184
5185
5186 if (invis != 0)
5187 tem = next_stop;
5188
5189
5190
5191 if (invis == 2)
5192 display_ellipsis_p = true;
5193 }
5194 while (invis != 0);
5195
5196
5197 if (it->bidi_p)
5198 {
5199 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5200 bool on_newline
5201 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5202 bool after_newline
5203 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5204
5205
5206
5207
5208
5209
5210
5211
5212 if (on_newline || after_newline)
5213 {
5214 struct text_pos tpos;
5215 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5216
5217 SET_TEXT_POS (tpos, newpos, bpos);
5218 reseat_1 (it, tpos, false);
5219
5220
5221
5222
5223
5224 if (on_newline)
5225 {
5226 it->bidi_it.first_elt = false;
5227 it->bidi_it.paragraph_dir = pdir;
5228 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5229 it->bidi_it.nchars = 1;
5230 it->bidi_it.ch_len = 1;
5231 }
5232 }
5233 else
5234 {
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5246 {
5247
5248
5249
5250
5251
5252
5253
5254 bidi_paragraph_init (it->paragraph_embedding,
5255 &it->bidi_it, true);
5256 }
5257 do
5258 {
5259 bidi_move_to_visually_next (&it->bidi_it);
5260 }
5261 while (it->stop_charpos <= it->bidi_it.charpos
5262 && it->bidi_it.charpos < newpos);
5263 IT_CHARPOS (*it) = it->bidi_it.charpos;
5264 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5265
5266
5267
5268
5269 if (IT_CHARPOS (*it) >= newpos)
5270 it->prev_stop = newpos;
5271 }
5272 }
5273 else
5274 {
5275 IT_CHARPOS (*it) = newpos;
5276 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5277 }
5278
5279 if (display_ellipsis_p)
5280 {
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293 if (!STRINGP (it->object))
5294 {
5295 it->position.charpos = newpos - 1;
5296 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5297 }
5298 }
5299
5300
5301
5302
5303
5304
5305
5306 if (NILP (overlay)
5307 && get_overlay_strings (it, it->stop_charpos))
5308 {
5309 handled = HANDLED_RECOMPUTE_PROPS;
5310 if (it->sp > 0)
5311 {
5312 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325 it->stack[it->sp - 1].stop_charpos
5326 = CHARPOS (it->stack[it->sp - 1].current.pos);
5327 }
5328 }
5329 else if (display_ellipsis_p)
5330 {
5331 it->ellipsis_p = true;
5332
5333
5334
5335 handled = HANDLED_RETURN;
5336 }
5337 }
5338 }
5339
5340 return handled;
5341 }
5342
5343
5344
5345
5346
5347 static void
5348 setup_for_ellipsis (struct it *it, int len)
5349 {
5350
5351
5352 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5353 {
5354 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5355 it->dpvec = v->contents;
5356 it->dpend = v->contents + v->header.size;
5357 }
5358 else
5359 {
5360
5361 it->dpvec = default_invis_vector;
5362 it->dpend = default_invis_vector + 3;
5363 }
5364
5365 it->dpvec_char_len = len;
5366 it->current.dpvec_index = 0;
5367 it->dpvec_face_id = -1;
5368
5369
5370
5371
5372
5373
5374
5375
5376 if (it->saved_face_id >= 0)
5377 it->face_id = it->saved_face_id;
5378
5379
5380
5381 if (it->method == GET_FROM_BUFFER)
5382 it->ignore_overlay_strings_at_pos_p = false;
5383
5384 it->method = GET_FROM_DISPLAY_VECTOR;
5385 it->ellipsis_p = true;
5386 }
5387
5388
5389 static Lisp_Object
5390 find_display_property (Lisp_Object disp, Lisp_Object prop)
5391 {
5392 if (NILP (disp))
5393 return Qnil;
5394
5395 if (VECTORP (disp))
5396 {
5397 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5398 {
5399 Lisp_Object elem = AREF (disp, i);
5400 if (CONSP (elem)
5401 && CONSP (XCDR (elem))
5402 && EQ (XCAR (elem), prop))
5403 return XCAR (XCDR (elem));
5404 }
5405 return Qnil;
5406 }
5407
5408 else if (CONSP (disp)
5409 && CONSP (XCAR (disp)))
5410 {
5411 while (!NILP (disp))
5412 {
5413 Lisp_Object elem = XCAR (disp);
5414 if (CONSP (elem)
5415 && CONSP (XCDR (elem))
5416 && EQ (XCAR (elem), prop))
5417 return XCAR (XCDR (elem));
5418
5419
5420
5421 if (CONSP (XCDR (disp)))
5422 disp = XCDR (disp);
5423 else
5424 disp = Qnil;
5425 }
5426 return Qnil;
5427 }
5428
5429 else if (CONSP (disp)
5430 && CONSP (XCDR (disp))
5431 && EQ (XCAR (disp), prop))
5432 return XCAR (XCDR (disp));
5433 else
5434 return Qnil;
5435 }
5436
5437 static Lisp_Object
5438 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5439 {
5440 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5441 Qdisplay, object),
5442 prop);
5443 }
5444
5445 static void
5446 display_min_width (struct it *it, ptrdiff_t bufpos,
5447 Lisp_Object object, Lisp_Object width_spec)
5448 {
5449
5450
5451 if (!NILP (it->min_width_property)
5452 && !EQ (width_spec, it->min_width_property))
5453 {
5454 if (!it->glyph_row)
5455 return;
5456
5457
5458
5459
5460
5461 if ((bufpos == 0
5462 && !EQ (it->min_width_property,
5463 get_display_property (0, Qmin_width, object)))
5464
5465
5466 || (bufpos > BEGV
5467 && EQ (it->min_width_property,
5468 get_display_property (bufpos - 1, Qmin_width, object))))
5469 {
5470 Lisp_Object w = Qnil;
5471 double width;
5472 #ifdef HAVE_WINDOW_SYSTEM
5473 if (FRAME_WINDOW_P (it->f))
5474 {
5475 struct font *font = NULL;
5476 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5477 font = face->font ? face->font : FRAME_FONT (it->f);
5478 calc_pixel_width_or_height (&width, it,
5479 XCAR (it->min_width_property),
5480 font, true, NULL);
5481 width -= it->current_x - it->min_width_start;
5482 w = list1 (make_int (width));
5483 }
5484 else
5485 #endif
5486 {
5487 calc_pixel_width_or_height (&width, it,
5488 XCAR (it->min_width_property),
5489 NULL, true, NULL);
5490 width -= (it->current_x - it->min_width_start) /
5491 FRAME_COLUMN_WIDTH (it->f);
5492 w = make_int (width);
5493 }
5494
5495
5496 it->object = list3 (Qspace, QCwidth, w);
5497 produce_stretch_glyph (it);
5498 if (it->area == TEXT_AREA)
5499 it->current_x += it->pixel_width;
5500 it->min_width_property = Qnil;
5501 }
5502 }
5503
5504
5505
5506
5507 if (CONSP (width_spec))
5508 {
5509 if (bufpos == BEGV
5510
5511 || (bufpos == 0
5512 && !EQ (it->min_width_property,
5513 get_display_property (0, Qmin_width, object)))
5514
5515 || (bufpos > BEGV
5516 && !EQ (width_spec,
5517 get_display_property (bufpos - 1, Qmin_width, object))))
5518 {
5519 it->min_width_property = width_spec;
5520 it->min_width_start = it->current_x;
5521 }
5522 }
5523 }
5524
5525 DEFUN ("get-display-property", Fget_display_property,
5526 Sget_display_property, 2, 4, 0,
5527 doc:
5528
5529
5530
5531
5532 )
5533 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5534 Lisp_Object properties)
5535 {
5536 if (NILP (properties))
5537 properties = Fget_text_property (position, Qdisplay, object);
5538 else
5539 CHECK_LIST (properties);
5540
5541 return find_display_property (properties, prop);
5542 }
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556 static enum prop_handled
5557 handle_display_prop (struct it *it)
5558 {
5559 Lisp_Object propval, object, overlay;
5560 struct text_pos *position;
5561 ptrdiff_t bufpos;
5562
5563 int display_replaced = 0;
5564
5565 if (STRINGP (it->string))
5566 {
5567 object = it->string;
5568 position = &it->current.string_pos;
5569 bufpos = CHARPOS (it->current.pos);
5570 }
5571 else
5572 {
5573 XSETWINDOW (object, it->w);
5574 position = &it->current.pos;
5575 bufpos = CHARPOS (*position);
5576 }
5577
5578
5579 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5580 it->space_width = Qnil;
5581 it->font_height = Qnil;
5582 it->voffset = 0;
5583
5584
5585
5586
5587 if (!it->string_from_display_prop_p)
5588 it->area = TEXT_AREA;
5589
5590 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5591 Qdisplay, object, &overlay);
5592
5593
5594 if (!STRINGP (it->string))
5595 object = it->w->contents;
5596
5597
5598 if (!NILP (it->min_width_property)
5599 && NILP (find_display_property (propval, Qmin_width)))
5600 display_min_width (it, bufpos, object, Qnil);
5601
5602 if (NILP (propval))
5603 return HANDLED_NORMALLY;
5604
5605
5606
5607 display_replaced = handle_display_spec (it, propval, object, overlay,
5608 position, bufpos,
5609 FRAME_WINDOW_P (it->f));
5610 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5611 }
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629 static int
5630 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5631 Lisp_Object overlay, struct text_pos *position,
5632 ptrdiff_t bufpos, bool frame_window_p)
5633 {
5634 int replacing = 0;
5635 bool enable_eval = true;
5636
5637
5638 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5639 {
5640 enable_eval = false;
5641 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5642 }
5643
5644 if (CONSP (spec)
5645
5646 && !EQ (XCAR (spec), Qimage)
5647 #ifdef HAVE_XWIDGETS
5648 && !EQ (XCAR (spec), Qxwidget)
5649 #endif
5650 && !EQ (XCAR (spec), Qspace)
5651 && !EQ (XCAR (spec), Qwhen)
5652 && !EQ (XCAR (spec), Qslice)
5653 && !EQ (XCAR (spec), Qspace_width)
5654 && !EQ (XCAR (spec), Qheight)
5655 && !EQ (XCAR (spec), Qraise)
5656
5657 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5658 && !EQ (XCAR (spec), Qleft_fringe)
5659 && !EQ (XCAR (spec), Qright_fringe)
5660 && !EQ (XCAR (spec), Qmin_width)
5661 && !NILP (XCAR (spec)))
5662 {
5663 for (; CONSP (spec); spec = XCDR (spec))
5664 {
5665 int rv = handle_single_display_spec (it, XCAR (spec), object,
5666 overlay, position, bufpos,
5667 replacing, frame_window_p,
5668 enable_eval);
5669 if (rv != 0)
5670 {
5671 replacing = rv;
5672
5673
5674 if (!it || STRINGP (object))
5675 break;
5676 }
5677 }
5678 }
5679 else if (VECTORP (spec))
5680 {
5681 ptrdiff_t i;
5682 for (i = 0; i < ASIZE (spec); ++i)
5683 {
5684 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5685 overlay, position, bufpos,
5686 replacing, frame_window_p,
5687 enable_eval);
5688 if (rv != 0)
5689 {
5690 replacing = rv;
5691
5692
5693 if (!it || STRINGP (object))
5694 break;
5695 }
5696 }
5697 }
5698 else
5699 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5700 bufpos, 0, frame_window_p,
5701 enable_eval);
5702 return replacing;
5703 }
5704
5705
5706
5707
5708 static struct text_pos
5709 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5710 {
5711 Lisp_Object end;
5712 struct text_pos end_pos;
5713
5714 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5715 Qdisplay, object, Qnil);
5716 CHARPOS (end_pos) = XFIXNAT (end);
5717 if (STRINGP (object))
5718 compute_string_pos (&end_pos, start_pos, it->string);
5719 else
5720 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5721
5722 return end_pos;
5723 }
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751 static int
5752 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5753 Lisp_Object overlay, struct text_pos *position,
5754 ptrdiff_t bufpos, int display_replaced,
5755 bool frame_window_p, bool enable_eval_p)
5756 {
5757 Lisp_Object form;
5758 Lisp_Object location, value;
5759 struct text_pos start_pos = *position;
5760 void *itdata = NULL;
5761
5762
5763
5764 form = Qt;
5765 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5766 {
5767 spec = XCDR (spec);
5768 if (!CONSP (spec))
5769 return 0;
5770 form = XCAR (spec);
5771 spec = XCDR (spec);
5772 }
5773
5774 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5775 form = Qnil;
5776 if (!NILP (form) && !EQ (form, Qt))
5777 {
5778 specpdl_ref count = SPECPDL_INDEX ();
5779
5780
5781
5782
5783
5784
5785 if (NILP (object))
5786 XSETBUFFER (object, current_buffer);
5787 specbind (Qobject, object);
5788 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5789 specbind (Qbuffer_position, make_fixnum (bufpos));
5790
5791
5792 itdata = bidi_shelve_cache ();
5793 form = safe_eval (form);
5794 bidi_unshelve_cache (itdata, false);
5795 form = unbind_to (count, form);
5796 }
5797
5798 if (NILP (form))
5799 return 0;
5800
5801
5802 if (CONSP (spec)
5803 && EQ (XCAR (spec), Qheight)
5804 && CONSP (XCDR (spec)))
5805 {
5806 if (it)
5807 {
5808 if (!FRAME_WINDOW_P (it->f))
5809 return 0;
5810
5811 it->font_height = XCAR (XCDR (spec));
5812 if (!NILP (it->font_height))
5813 {
5814 int new_height = -1;
5815
5816 if (CONSP (it->font_height)
5817 && (EQ (XCAR (it->font_height), Qplus)
5818 || EQ (XCAR (it->font_height), Qminus))
5819 && CONSP (XCDR (it->font_height))
5820 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5821 {
5822
5823 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5824 if (EQ (XCAR (it->font_height), Qplus))
5825 steps = - steps;
5826 it->face_id = smaller_face (it->f, it->face_id, steps);
5827 }
5828 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5829 {
5830
5831
5832 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5833 Lisp_Object height;
5834 itdata = bidi_shelve_cache ();
5835 height = safe_call1 (it->font_height,
5836 face->lface[LFACE_HEIGHT_INDEX]);
5837 bidi_unshelve_cache (itdata, false);
5838 if (NUMBERP (height))
5839 new_height = XFLOATINT (height);
5840 }
5841 else if (NUMBERP (it->font_height))
5842 {
5843
5844 struct face *f;
5845
5846 f = FACE_FROM_ID (it->f,
5847 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5848 new_height = (XFLOATINT (it->font_height)
5849 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5850 }
5851 else if (enable_eval_p)
5852 {
5853
5854
5855 specpdl_ref count = SPECPDL_INDEX ();
5856 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5857
5858 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5859 itdata = bidi_shelve_cache ();
5860 value = safe_eval (it->font_height);
5861 bidi_unshelve_cache (itdata, false);
5862 value = unbind_to (count, value);
5863
5864 if (NUMBERP (value))
5865 new_height = XFLOATINT (value);
5866 }
5867
5868 if (new_height > 0)
5869 it->face_id = face_with_height (it->f, it->face_id, new_height);
5870 }
5871 }
5872
5873 return 0;
5874 }
5875
5876
5877 if (CONSP (spec)
5878 && EQ (XCAR (spec), Qspace_width)
5879 && CONSP (XCDR (spec)))
5880 {
5881 if (it)
5882 {
5883 if (!FRAME_WINDOW_P (it->f))
5884 return 0;
5885
5886 value = XCAR (XCDR (spec));
5887 if (NUMBERP (value) && XFLOATINT (value) > 0)
5888 it->space_width = value;
5889 }
5890
5891 return 0;
5892 }
5893
5894
5895 if (CONSP (spec)
5896 && EQ (XCAR (spec), Qmin_width)
5897 && CONSP (XCDR (spec))
5898 && CONSP (XCAR (XCDR (spec))))
5899 {
5900 if (it)
5901 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5902 return 0;
5903 }
5904
5905
5906 if (CONSP (spec)
5907 && EQ (XCAR (spec), Qslice))
5908 {
5909 Lisp_Object tem;
5910
5911 if (it)
5912 {
5913 if (!FRAME_WINDOW_P (it->f))
5914 return 0;
5915
5916 if (tem = XCDR (spec), CONSP (tem))
5917 {
5918 it->slice.x = XCAR (tem);
5919 if (tem = XCDR (tem), CONSP (tem))
5920 {
5921 it->slice.y = XCAR (tem);
5922 if (tem = XCDR (tem), CONSP (tem))
5923 {
5924 it->slice.width = XCAR (tem);
5925 if (tem = XCDR (tem), CONSP (tem))
5926 it->slice.height = XCAR (tem);
5927 }
5928 }
5929 }
5930 }
5931
5932 return 0;
5933 }
5934
5935
5936 if (CONSP (spec)
5937 && EQ (XCAR (spec), Qraise)
5938 && CONSP (XCDR (spec)))
5939 {
5940 if (it)
5941 {
5942 if (!FRAME_WINDOW_P (it->f))
5943 return 0;
5944
5945 #ifdef HAVE_WINDOW_SYSTEM
5946 value = XCAR (XCDR (spec));
5947 if (NUMBERP (value))
5948 {
5949 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5950 it->voffset = - (XFLOATINT (value)
5951 * (normal_char_height (face->font, -1)));
5952 }
5953 #endif
5954 }
5955
5956 return 0;
5957 }
5958
5959
5960
5961 if (it && it->string_from_display_prop_p)
5962 return 0;
5963
5964
5965
5966 if (it)
5967 {
5968 start_pos = *position;
5969 *position = display_prop_end (it, object, start_pos);
5970
5971
5972
5973
5974
5975
5976
5977 if (!NILP (overlay))
5978 {
5979 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5980
5981
5982
5983
5984
5985
5986
5987 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
5988
5989 if (ovendpos > CHARPOS (*position))
5990 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
5991 }
5992 }
5993 value = Qnil;
5994
5995
5996
5997 if (it)
5998 it->stop_charpos = position->charpos;
5999
6000
6001
6002 if (CONSP (spec)
6003 && (EQ (XCAR (spec), Qleft_fringe)
6004 || EQ (XCAR (spec), Qright_fringe))
6005 && CONSP (XCDR (spec)))
6006 {
6007 if (it)
6008 {
6009 if (!FRAME_WINDOW_P (it->f))
6010
6011
6012 {
6013
6014
6015
6016
6017 if (it->bidi_p)
6018 {
6019 it->position = *position;
6020 iterate_out_of_display_property (it);
6021 *position = it->position;
6022 }
6023 return 1;
6024 }
6025 }
6026 else if (!frame_window_p)
6027 return 1;
6028
6029 #ifdef HAVE_WINDOW_SYSTEM
6030 value = XCAR (XCDR (spec));
6031 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6032 if (! fringe_bitmap)
6033
6034
6035 {
6036 if (it && it->bidi_p)
6037 {
6038 it->position = *position;
6039 iterate_out_of_display_property (it);
6040 *position = it->position;
6041 }
6042 return 1;
6043 }
6044
6045 if (it)
6046 {
6047 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6048
6049 if (CONSP (XCDR (XCDR (spec))))
6050 {
6051 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6052 int face_id2;
6053
6054
6055
6056 specpdl_ref count1 = SPECPDL_INDEX ();
6057 specbind (Qinhibit_quit, Qt);
6058 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6059 FRINGE_FACE_ID, false);
6060 unbind_to (count1, Qnil);
6061 if (face_id2 >= 0)
6062 face_id = face_id2;
6063 }
6064
6065
6066
6067 push_it (it, position);
6068
6069 it->area = TEXT_AREA;
6070 it->what = IT_IMAGE;
6071 it->image_id = -1;
6072 it->position = start_pos;
6073 it->object = NILP (object) ? it->w->contents : object;
6074 it->method = GET_FROM_IMAGE;
6075 it->from_overlay = Qnil;
6076 it->face_id = face_id;
6077 it->from_disp_prop_p = true;
6078
6079
6080
6081
6082 *position = start_pos;
6083
6084 if (EQ (XCAR (spec), Qleft_fringe))
6085 {
6086 it->left_user_fringe_bitmap = fringe_bitmap;
6087 it->left_user_fringe_face_id = face_id;
6088 }
6089 else
6090 {
6091 it->right_user_fringe_bitmap = fringe_bitmap;
6092 it->right_user_fringe_face_id = face_id;
6093 }
6094 }
6095 #endif
6096 return 1;
6097 }
6098
6099
6100
6101
6102 location = Qunbound;
6103 if (CONSP (spec) && CONSP (XCAR (spec)))
6104 {
6105 Lisp_Object tem;
6106
6107 value = XCDR (spec);
6108 if (CONSP (value))
6109 value = XCAR (value);
6110
6111 tem = XCAR (spec);
6112 if (EQ (XCAR (tem), Qmargin)
6113 && (tem = XCDR (tem),
6114 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6115 (NILP (tem)
6116 || EQ (tem, Qleft_margin)
6117 || EQ (tem, Qright_margin))))
6118 location = tem;
6119 }
6120
6121 if (BASE_EQ (location, Qunbound))
6122 {
6123 location = Qnil;
6124 value = spec;
6125 }
6126
6127
6128
6129
6130
6131
6132
6133
6134 bool valid_p = (STRINGP (value)
6135 #ifdef HAVE_WINDOW_SYSTEM
6136 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6137 && valid_image_p (value))
6138 #endif
6139 || (CONSP (value) && EQ (XCAR (value), Qspace))
6140 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6141 && valid_xwidget_spec_p (value)));
6142
6143 if (valid_p && display_replaced == 0)
6144 {
6145 int retval = 1;
6146
6147 if (!it)
6148 {
6149
6150
6151
6152 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6153 retval = 2;
6154 return retval;
6155 }
6156
6157
6158
6159 push_it (it, position);
6160 it->from_overlay = overlay;
6161 it->from_disp_prop_p = true;
6162
6163 if (NILP (location))
6164 it->area = TEXT_AREA;
6165 else if (EQ (location, Qleft_margin))
6166 it->area = LEFT_MARGIN_AREA;
6167 else
6168 it->area = RIGHT_MARGIN_AREA;
6169
6170 if (STRINGP (value))
6171 {
6172 it->string = value;
6173 it->multibyte_p = STRING_MULTIBYTE (it->string);
6174 it->current.overlay_string_index = -1;
6175 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6176 it->end_charpos = it->string_nchars = SCHARS (it->string);
6177 it->method = GET_FROM_STRING;
6178 it->stop_charpos = 0;
6179 it->prev_stop = 0;
6180 it->base_level_stop = 0;
6181 it->string_from_display_prop_p = true;
6182 it->cmp_it.id = -1;
6183
6184
6185
6186 if (BUFFERP (object))
6187 *position = start_pos;
6188
6189
6190
6191
6192 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6193 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6194 else
6195 it->paragraph_embedding = L2R;
6196
6197
6198 if (it->bidi_p)
6199 {
6200 it->bidi_it.string.lstring = it->string;
6201 it->bidi_it.string.s = NULL;
6202 it->bidi_it.string.schars = it->end_charpos;
6203 it->bidi_it.string.bufpos = bufpos;
6204 it->bidi_it.string.from_disp_str = true;
6205 it->bidi_it.string.unibyte = !it->multibyte_p;
6206 it->bidi_it.w = it->w;
6207 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6208 }
6209 }
6210 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6211 {
6212 it->method = GET_FROM_STRETCH;
6213 it->object = value;
6214 *position = it->position = start_pos;
6215 retval = 1 + (it->area == TEXT_AREA);
6216 }
6217 else if (valid_xwidget_spec_p (value))
6218 {
6219 it->what = IT_XWIDGET;
6220 it->method = GET_FROM_XWIDGET;
6221 it->position = start_pos;
6222 it->object = NILP (object) ? it->w->contents : object;
6223 *position = start_pos;
6224 it->xwidget = lookup_xwidget (value);
6225 }
6226 #ifdef HAVE_WINDOW_SYSTEM
6227 else
6228 {
6229 specpdl_ref count = SPECPDL_INDEX ();
6230
6231 it->what = IT_IMAGE;
6232
6233
6234
6235 specbind (Qinhibit_quit, Qt);
6236 it->image_id = lookup_image (it->f, value, it->face_id);
6237 unbind_to (count, Qnil);
6238 it->position = start_pos;
6239 it->object = NILP (object) ? it->w->contents : object;
6240 it->method = GET_FROM_IMAGE;
6241
6242
6243
6244
6245 *position = start_pos;
6246 }
6247 #endif
6248
6249 return retval;
6250 }
6251
6252
6253
6254 *position = start_pos;
6255 return 0;
6256 }
6257
6258
6259
6260
6261
6262
6263 bool
6264 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6265 ptrdiff_t charpos, ptrdiff_t bytepos)
6266 {
6267 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6268 struct text_pos position;
6269
6270 SET_TEXT_POS (position, charpos, bytepos);
6271 return (handle_display_spec (NULL, prop, Qnil, overlay,
6272 &position, charpos, frame_window_p)
6273 != 0);
6274 }
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285 static bool
6286 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6287 {
6288 if (EQ (string, prop))
6289 return true;
6290
6291
6292 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6293 {
6294 prop = XCDR (prop);
6295 if (!CONSP (prop))
6296 return false;
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307 prop = XCDR (prop);
6308 }
6309
6310 if (CONSP (prop))
6311
6312 if (EQ (XCAR (prop), Qmargin))
6313 {
6314 prop = XCDR (prop);
6315 if (!CONSP (prop))
6316 return false;
6317
6318 prop = XCDR (prop);
6319 if (!CONSP (prop))
6320 return false;
6321 }
6322
6323 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6324 }
6325
6326
6327
6328
6329 static bool
6330 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6331 {
6332 if (CONSP (prop)
6333 && !EQ (XCAR (prop), Qwhen)
6334 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6335 {
6336
6337 while (CONSP (prop))
6338 {
6339 if (single_display_spec_string_p (XCAR (prop), string))
6340 return true;
6341 prop = XCDR (prop);
6342 }
6343 }
6344 else if (VECTORP (prop))
6345 {
6346
6347 ptrdiff_t i;
6348 for (i = 0; i < ASIZE (prop); ++i)
6349 if (single_display_spec_string_p (AREF (prop, i), string))
6350 return true;
6351 }
6352 else
6353 return single_display_spec_string_p (prop, string);
6354
6355 return false;
6356 }
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368 static ptrdiff_t
6369 string_buffer_position_lim (Lisp_Object string,
6370 ptrdiff_t from, ptrdiff_t to, bool back_p)
6371 {
6372 Lisp_Object limit, prop, pos;
6373 bool found = false;
6374
6375 pos = make_fixnum (max (from, BEGV));
6376
6377 if (!back_p)
6378 {
6379 limit = make_fixnum (min (to, ZV));
6380 while (!found && !EQ (pos, limit))
6381 {
6382 prop = Fget_char_property (pos, Qdisplay, Qnil);
6383 if (!NILP (prop) && display_prop_string_p (prop, string))
6384 found = true;
6385 else
6386 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6387 limit);
6388 }
6389 }
6390 else
6391 {
6392 limit = make_fixnum (max (to, BEGV));
6393 while (!found && !EQ (pos, limit))
6394 {
6395 prop = Fget_char_property (pos, Qdisplay, Qnil);
6396 if (!NILP (prop) && display_prop_string_p (prop, string))
6397 found = true;
6398 else
6399 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6400 limit);
6401 }
6402 }
6403
6404 return found ? XFIXNUM (pos) : 0;
6405 }
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416 static ptrdiff_t
6417 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6418 {
6419 const int MAX_DISTANCE = 1000;
6420 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6421 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6422 forward_limit, false);
6423
6424 if (!found)
6425 {
6426 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6427 found = string_buffer_position_lim (string, around_charpos,
6428 backward_limit, true);
6429 }
6430 return found;
6431 }
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442 static enum prop_handled
6443 handle_composition_prop (struct it *it)
6444 {
6445 Lisp_Object prop, string;
6446 ptrdiff_t pos, pos_byte, start, end;
6447
6448 if (STRINGP (it->string))
6449 {
6450 unsigned char *s;
6451
6452 pos = IT_STRING_CHARPOS (*it);
6453 pos_byte = IT_STRING_BYTEPOS (*it);
6454 string = it->string;
6455 s = SDATA (string) + pos_byte;
6456 if (STRING_MULTIBYTE (string))
6457 it->c = STRING_CHAR (s);
6458 else
6459 it->c = *s;
6460 }
6461 else
6462 {
6463 pos = IT_CHARPOS (*it);
6464 pos_byte = IT_BYTEPOS (*it);
6465 string = Qnil;
6466 it->c = FETCH_CHAR (pos_byte);
6467 }
6468
6469
6470
6471
6472 if (find_composition (pos, -1, &start, &end, &prop, string)
6473 && composition_valid_p (start, end, prop)
6474 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6475 {
6476 if (start < pos)
6477
6478
6479
6480 return HANDLED_NORMALLY;
6481 if (start != pos)
6482 {
6483 if (STRINGP (it->string))
6484 pos_byte = string_char_to_byte (it->string, start);
6485 else
6486 pos_byte = CHAR_TO_BYTE (start);
6487 }
6488 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6489 prop, string);
6490
6491 if (it->cmp_it.id >= 0)
6492 {
6493 it->cmp_it.ch = -1;
6494 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6495 it->cmp_it.nglyphs = -1;
6496 }
6497 }
6498
6499 return HANDLED_NORMALLY;
6500 }
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511 struct overlay_entry
6512 {
6513 Lisp_Object overlay;
6514 Lisp_Object string;
6515 EMACS_INT priority;
6516 bool after_string_p;
6517 };
6518
6519
6520
6521
6522
6523 static enum prop_handled
6524 handle_overlay_change (struct it *it)
6525 {
6526 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6527 return HANDLED_RECOMPUTE_PROPS;
6528 else
6529 return HANDLED_NORMALLY;
6530 }
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540 static void
6541 next_overlay_string (struct it *it)
6542 {
6543 ++it->current.overlay_string_index;
6544 if (it->current.overlay_string_index == it->n_overlay_strings)
6545 {
6546
6547
6548
6549
6550 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6551 pop_it (it);
6552 eassert (it->sp > 0
6553 || (NILP (it->string)
6554 && it->method == GET_FROM_BUFFER
6555 && it->stop_charpos >= BEGV
6556 && it->stop_charpos <= it->end_charpos));
6557 it->current.overlay_string_index = -1;
6558 it->n_overlay_strings = 0;
6559
6560
6561
6562
6563 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6564 pop_it (it);
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6575 it->ignore_overlay_strings_at_pos_p = true;
6576
6577
6578
6579
6580 if (NILP (it->string)
6581 && IT_CHARPOS (*it) >= it->end_charpos
6582 && it->overlay_strings_charpos >= it->end_charpos)
6583 it->overlay_strings_at_end_processed_p = true;
6584
6585
6586
6587
6588
6589
6590
6591 it->overlay_strings_charpos = -1;
6592 }
6593 else
6594 {
6595
6596
6597
6598
6599
6600
6601 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6602
6603 if (it->current.overlay_string_index && i == 0)
6604 load_overlay_strings (it, it->overlay_strings_charpos);
6605
6606
6607
6608 it->string = it->overlay_strings[i];
6609 it->multibyte_p = STRING_MULTIBYTE (it->string);
6610 SET_TEXT_POS (it->current.string_pos, 0, 0);
6611 it->method = GET_FROM_STRING;
6612 it->stop_charpos = 0;
6613 it->end_charpos = SCHARS (it->string);
6614 if (it->cmp_it.stop_pos >= 0)
6615 it->cmp_it.stop_pos = 0;
6616 it->prev_stop = 0;
6617 it->base_level_stop = 0;
6618
6619
6620 if (it->bidi_p)
6621 {
6622 it->bidi_it.string.lstring = it->string;
6623 it->bidi_it.string.s = NULL;
6624 it->bidi_it.string.schars = SCHARS (it->string);
6625 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6626 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6627 it->bidi_it.string.unibyte = !it->multibyte_p;
6628 it->bidi_it.w = it->w;
6629 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6630 }
6631 }
6632
6633 CHECK_IT (it);
6634 }
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653 static int
6654 compare_overlay_entries (const void *e1, const void *e2)
6655 {
6656 struct overlay_entry const *entry1 = e1;
6657 struct overlay_entry const *entry2 = e2;
6658 int result;
6659
6660 if (entry1->after_string_p != entry2->after_string_p)
6661 {
6662
6663
6664 if (EQ (entry1->overlay, entry2->overlay))
6665 result = entry1->after_string_p ? 1 : -1;
6666 else
6667 result = entry1->after_string_p ? -1 : 1;
6668 }
6669 else if (entry1->priority != entry2->priority)
6670 {
6671 if (entry1->after_string_p)
6672
6673 result = entry2->priority < entry1->priority ? -1 : 1;
6674 else
6675
6676 result = entry1->priority < entry2->priority ? -1 : 1;
6677 }
6678 else
6679 result = 0;
6680
6681 return result;
6682 }
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709 static void
6710 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6711 {
6712 ptrdiff_t n = 0;
6713 struct overlay_entry entriesbuf[20];
6714 ptrdiff_t size = ARRAYELTS (entriesbuf);
6715 struct overlay_entry *entries = entriesbuf;
6716 struct itree_node *node;
6717
6718 USE_SAFE_ALLOCA;
6719
6720 if (charpos <= 0)
6721 charpos = IT_CHARPOS (*it);
6722
6723
6724
6725
6726
6727 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6728 do \
6729 { \
6730 Lisp_Object priority; \
6731 \
6732 if (n == size) \
6733 { \
6734 struct overlay_entry *old = entries; \
6735 SAFE_NALLOCA (entries, 2, size); \
6736 memcpy (entries, old, size * sizeof *entries); \
6737 size *= 2; \
6738 } \
6739 \
6740 entries[n].string = (STRING); \
6741 entries[n].overlay = (OVERLAY); \
6742 priority = Foverlay_get ((OVERLAY), Qpriority); \
6743 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6744 entries[n].after_string_p = (AFTER_P); \
6745 ++n; \
6746 } \
6747 while (false)
6748
6749
6750
6751 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6752 {
6753 Lisp_Object overlay = node->data;
6754 eassert (OVERLAYP (overlay));
6755 ptrdiff_t start = node->begin;
6756 ptrdiff_t end = node->end;
6757
6758
6759
6760 if (end != charpos && start != charpos)
6761 continue;
6762
6763
6764 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6765 if (WINDOWP (window) && XWINDOW (window) != it->w)
6766 continue;
6767
6768
6769
6770
6771 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6772 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6773
6774
6775 Lisp_Object str;
6776 if ((start == charpos || (end == charpos && invis != 0))
6777 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6778 && SCHARS (str))
6779 RECORD_OVERLAY_STRING (overlay, str, false);
6780
6781
6782 if ((end == charpos || (start == charpos && invis != 0))
6783 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6784 && SCHARS (str))
6785 RECORD_OVERLAY_STRING (overlay, str, true);
6786 }
6787
6788 #undef RECORD_OVERLAY_STRING
6789
6790
6791 if (n > 1)
6792 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6793
6794
6795 it->n_overlay_strings = n;
6796 it->overlay_strings_charpos = charpos;
6797
6798
6799
6800
6801 ptrdiff_t j = it->current.overlay_string_index;
6802 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6803 {
6804 it->overlay_strings[i] = entries[j].string;
6805 it->string_overlays[i] = entries[j].overlay;
6806 }
6807
6808 CHECK_IT (it);
6809 SAFE_FREE ();
6810 }
6811
6812
6813
6814
6815
6816
6817 static bool
6818 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6819 {
6820
6821
6822
6823
6824
6825
6826
6827 it->current.overlay_string_index = 0;
6828 load_overlay_strings (it, charpos);
6829
6830
6831
6832
6833 if (it->n_overlay_strings)
6834 {
6835
6836
6837
6838 if (compute_stop_p)
6839 compute_stop_pos (it);
6840 eassert (it->face_id >= 0);
6841
6842
6843
6844 eassert (!compute_stop_p || it->sp == 0);
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854 if (!(!it->bidi_p
6855 && STRINGP (it->string) && !SCHARS (it->string)))
6856 push_it (it, NULL);
6857
6858
6859
6860 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6861 it->string = it->overlay_strings[0];
6862 it->from_overlay = Qnil;
6863 it->stop_charpos = 0;
6864 eassert (STRINGP (it->string));
6865 it->end_charpos = SCHARS (it->string);
6866 it->prev_stop = 0;
6867 it->base_level_stop = 0;
6868 it->multibyte_p = STRING_MULTIBYTE (it->string);
6869 it->method = GET_FROM_STRING;
6870 it->from_disp_prop_p = 0;
6871 it->cmp_it.id = -1;
6872
6873
6874
6875 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6876 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6877 else
6878 it->paragraph_embedding = L2R;
6879
6880
6881 if (it->bidi_p)
6882 {
6883 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6884
6885 it->bidi_it.string.lstring = it->string;
6886 it->bidi_it.string.s = NULL;
6887 it->bidi_it.string.schars = SCHARS (it->string);
6888 it->bidi_it.string.bufpos = pos;
6889 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6890 it->bidi_it.string.unibyte = !it->multibyte_p;
6891 it->bidi_it.w = it->w;
6892 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6893 }
6894 return true;
6895 }
6896
6897 it->current.overlay_string_index = -1;
6898 return false;
6899 }
6900
6901 static bool
6902 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6903 {
6904 it->string = Qnil;
6905 it->method = GET_FROM_BUFFER;
6906
6907 get_overlay_strings_1 (it, charpos, true);
6908
6909 CHECK_IT (it);
6910
6911
6912 return STRINGP (it->string);
6913 }
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927 static void
6928 push_it (struct it *it, struct text_pos *position)
6929 {
6930 struct iterator_stack_entry *p;
6931
6932 eassert (it->sp < IT_STACK_SIZE);
6933 p = it->stack + it->sp;
6934
6935 p->stop_charpos = it->stop_charpos;
6936 p->prev_stop = it->prev_stop;
6937 p->base_level_stop = it->base_level_stop;
6938 p->cmp_it = it->cmp_it;
6939 eassert (it->face_id >= 0);
6940 p->face_id = it->face_id;
6941 p->string = it->string;
6942 p->method = it->method;
6943 p->from_overlay = it->from_overlay;
6944 switch (p->method)
6945 {
6946 case GET_FROM_IMAGE:
6947 p->u.image.object = it->object;
6948 p->u.image.image_id = it->image_id;
6949 p->u.image.slice = it->slice;
6950 break;
6951 case GET_FROM_STRETCH:
6952 p->u.stretch.object = it->object;
6953 break;
6954 case GET_FROM_XWIDGET:
6955 p->u.xwidget.object = it->object;
6956 break;
6957 case GET_FROM_BUFFER:
6958 case GET_FROM_DISPLAY_VECTOR:
6959 case GET_FROM_STRING:
6960 case GET_FROM_C_STRING:
6961 break;
6962 default:
6963 emacs_abort ();
6964 }
6965 p->position = position ? *position : it->position;
6966 p->current = it->current;
6967 p->end_charpos = it->end_charpos;
6968 p->string_nchars = it->string_nchars;
6969 p->area = it->area;
6970 p->multibyte_p = it->multibyte_p;
6971 p->avoid_cursor_p = it->avoid_cursor_p;
6972 p->space_width = it->space_width;
6973 p->font_height = it->font_height;
6974 p->voffset = it->voffset;
6975 p->string_from_display_prop_p = it->string_from_display_prop_p;
6976 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6977 p->display_ellipsis_p = false;
6978 p->line_wrap = it->line_wrap;
6979 p->bidi_p = it->bidi_p;
6980 p->paragraph_embedding = it->paragraph_embedding;
6981 p->from_disp_prop_p = it->from_disp_prop_p;
6982 ++it->sp;
6983
6984
6985 if (it->bidi_p)
6986 bidi_push_it (&it->bidi_it);
6987 }
6988
6989 static void
6990 iterate_out_of_display_property (struct it *it)
6991 {
6992 bool buffer_p = !STRINGP (it->string);
6993 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
6994 ptrdiff_t bob = (buffer_p ? BEGV : 0);
6995
6996 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
6997
6998
6999
7000
7001 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
7002 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
7003
7004 while (it->bidi_it.charpos >= bob
7005 && it->prev_stop <= it->bidi_it.charpos
7006 && it->bidi_it.charpos < CHARPOS (it->position)
7007 && it->bidi_it.charpos < eob)
7008 bidi_move_to_visually_next (&it->bidi_it);
7009
7010
7011 if (it->bidi_it.charpos > CHARPOS (it->position))
7012 it->prev_stop = CHARPOS (it->position);
7013
7014
7015 if (it->bidi_it.charpos != CHARPOS (it->position))
7016 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7017 if (buffer_p)
7018 it->current.pos = it->position;
7019 else
7020 it->current.string_pos = it->position;
7021 }
7022
7023
7024
7025
7026
7027 static void
7028 restore_face_box_flags (struct it *it, int prev_face_id)
7029 {
7030 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7031
7032 if (face)
7033 {
7034 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7035
7036 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7037 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7038 && (prev_face == NULL
7039 || prev_face->box == FACE_NO_BOX));
7040 it->face_box_p = face->box != FACE_NO_BOX;
7041 }
7042 }
7043
7044
7045
7046
7047
7048
7049
7050 static void
7051 pop_it (struct it *it)
7052 {
7053 struct iterator_stack_entry *p;
7054 bool from_display_prop = it->from_disp_prop_p;
7055 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7056 int prev_face_id = it->face_id;
7057
7058 eassert (it->sp > 0);
7059 --it->sp;
7060 p = it->stack + it->sp;
7061 it->stop_charpos = p->stop_charpos;
7062 it->prev_stop = p->prev_stop;
7063 it->base_level_stop = p->base_level_stop;
7064 it->cmp_it = p->cmp_it;
7065 it->face_id = p->face_id;
7066 it->current = p->current;
7067 it->position = p->position;
7068 it->string = p->string;
7069 it->from_overlay = p->from_overlay;
7070 if (NILP (it->string))
7071 SET_TEXT_POS (it->current.string_pos, -1, -1);
7072 it->method = p->method;
7073 switch (it->method)
7074 {
7075 case GET_FROM_IMAGE:
7076 it->image_id = p->u.image.image_id;
7077 it->object = p->u.image.object;
7078 it->slice = p->u.image.slice;
7079 break;
7080 case GET_FROM_XWIDGET:
7081 it->object = p->u.xwidget.object;
7082 break;
7083 case GET_FROM_STRETCH:
7084 it->object = p->u.stretch.object;
7085 break;
7086 case GET_FROM_BUFFER:
7087 {
7088 restore_face_box_flags (it, prev_face_id);
7089 it->object = it->w->contents;
7090 }
7091 break;
7092 case GET_FROM_STRING:
7093 {
7094 restore_face_box_flags (it, prev_face_id);
7095 it->object = it->string;
7096 }
7097 break;
7098 case GET_FROM_DISPLAY_VECTOR:
7099 if (it->s)
7100 it->method = GET_FROM_C_STRING;
7101 else if (STRINGP (it->string))
7102 it->method = GET_FROM_STRING;
7103 else
7104 {
7105 it->method = GET_FROM_BUFFER;
7106 it->object = it->w->contents;
7107 }
7108 break;
7109 case GET_FROM_C_STRING:
7110 break;
7111 default:
7112 emacs_abort ();
7113 }
7114 it->end_charpos = p->end_charpos;
7115 it->string_nchars = p->string_nchars;
7116 it->area = p->area;
7117 it->multibyte_p = p->multibyte_p;
7118 it->avoid_cursor_p = p->avoid_cursor_p;
7119 it->space_width = p->space_width;
7120 it->font_height = p->font_height;
7121 it->voffset = p->voffset;
7122 it->string_from_display_prop_p = p->string_from_display_prop_p;
7123 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7124 it->line_wrap = p->line_wrap;
7125 it->bidi_p = p->bidi_p;
7126 it->paragraph_embedding = p->paragraph_embedding;
7127 it->from_disp_prop_p = p->from_disp_prop_p;
7128 if (it->bidi_p)
7129 {
7130 bidi_pop_it (&it->bidi_it);
7131
7132
7133
7134
7135
7136
7137
7138 if (from_display_prop
7139 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7140 iterate_out_of_display_property (it);
7141
7142 eassert ((BUFFERP (it->object)
7143 && IT_CHARPOS (*it) == it->bidi_it.charpos
7144 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7145 || (STRINGP (it->object)
7146 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7147 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7148 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7149
7150
7151
7152
7153
7154
7155 || it->sp > 0);
7156 }
7157
7158
7159
7160 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7161 it->ignore_overlay_strings_at_pos_p = false;
7162 }
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172 static void
7173 back_to_previous_line_start (struct it *it)
7174 {
7175 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7176
7177 dec_both (&cp, &bp);
7178 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7179 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7180 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7181 }
7182
7183
7184
7185
7186
7187 static bool
7188 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7189 {
7190 struct itree_node *node;
7191
7192 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7193 {
7194 Lisp_Object overlay = node->data;
7195 eassert (OVERLAYP (overlay));
7196
7197
7198 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7199 if (WINDOWP (window) && XWINDOW (window) != w)
7200 continue;
7201
7202 ptrdiff_t ostart = node->begin;
7203 ptrdiff_t oend = node->end;
7204
7205
7206 if (!((startpos < oend && ostart < endpos)
7207 || (ostart == oend
7208 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7209 continue;
7210
7211 Lisp_Object str;
7212 str = Foverlay_get (overlay, Qbefore_string);
7213 if (STRINGP (str) && SCHARS (str)
7214 && memchr (SDATA (str), '\n', SBYTES (str)))
7215 return true;
7216 str = Foverlay_get (overlay, Qafter_string);
7217 if (STRINGP (str) && SCHARS (str)
7218 && memchr (SDATA (str), '\n', SBYTES (str)))
7219 return true;
7220 }
7221
7222
7223 Lisp_Object cpos = make_fixnum (startpos);
7224 Lisp_Object limpos = make_fixnum (endpos);
7225
7226 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7227 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7228 {
7229 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7230 Lisp_Object string = string_from_display_spec (spec);
7231 if (STRINGP (string)
7232 && memchr (SDATA (string), '\n', SBYTES (string)))
7233 return true;
7234 }
7235
7236 return false;
7237 }
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261 static bool
7262 forward_to_next_line_start (struct it *it, bool *skipped_p,
7263 struct bidi_it *bidi_it_prev)
7264 {
7265 ptrdiff_t old_selective;
7266 bool newline_found_p = false;
7267 int n;
7268 const int MAX_NEWLINE_DISTANCE = 500;
7269
7270
7271
7272 if (it->what == IT_CHARACTER
7273 && it->c == '\n'
7274 && CHARPOS (it->position) == IT_CHARPOS (*it))
7275 {
7276 if (it->bidi_p && bidi_it_prev)
7277 *bidi_it_prev = it->bidi_it;
7278 set_iterator_to_next (it, false);
7279 it->c = 0;
7280 return true;
7281 }
7282
7283
7284
7285
7286
7287 old_selective = it->selective;
7288 it->selective = 0;
7289
7290
7291
7292
7293 for (n = 0;
7294 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7295 n += !STRINGP (it->string))
7296 {
7297 if (!get_next_display_element (it))
7298 return false;
7299 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7300 if (newline_found_p && it->bidi_p && bidi_it_prev)
7301 *bidi_it_prev = it->bidi_it;
7302 set_iterator_to_next (it, false);
7303 }
7304
7305
7306
7307 if (!newline_found_p)
7308 {
7309 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7310 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7311 1, &bytepos);
7312 eassert (!STRINGP (it->string));
7313
7314
7315
7316
7317 bool no_strings_with_newlines = it->stop_charpos >= limit;
7318
7319 if (!no_strings_with_newlines)
7320 {
7321 if (!(current_buffer->long_line_optimizations_p
7322 && it->line_wrap == TRUNCATE))
7323 {
7324
7325
7326 Lisp_Object pos =
7327 Fnext_single_property_change (make_fixnum (start),
7328 Qdisplay, Qnil,
7329 make_fixnum (limit));
7330 no_strings_with_newlines =
7331 (NILP (pos) || XFIXNAT (pos) == limit)
7332 && next_overlay_change (start) == ZV;
7333 }
7334 else
7335 {
7336
7337
7338
7339
7340 no_strings_with_newlines =
7341 !strings_with_newlines (start, limit, it->w);
7342 }
7343 }
7344
7345
7346
7347
7348 if (no_strings_with_newlines)
7349 {
7350 if (!it->bidi_p || !bidi_it_prev)
7351 {
7352
7353 IT_CHARPOS (*it) = limit;
7354 IT_BYTEPOS (*it) = bytepos;
7355 }
7356 else
7357 {
7358
7359
7360
7361 struct bidi_it bprev;
7362
7363
7364
7365
7366 if (it->bidi_it.disp_pos < limit)
7367 {
7368 it->bidi_it.disp_pos = limit;
7369 it->bidi_it.disp_prop = 0;
7370 }
7371 do {
7372 bprev = it->bidi_it;
7373 bidi_move_to_visually_next (&it->bidi_it);
7374 } while (it->bidi_it.charpos != limit);
7375 IT_CHARPOS (*it) = limit;
7376 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7377 if (bidi_it_prev)
7378 *bidi_it_prev = bprev;
7379 }
7380 *skipped_p = newline_found_p = true;
7381 }
7382 else
7383 {
7384
7385 while (!newline_found_p)
7386 {
7387 if (!get_next_display_element (it))
7388 break;
7389 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7390 if (newline_found_p && it->bidi_p && bidi_it_prev)
7391 *bidi_it_prev = it->bidi_it;
7392 set_iterator_to_next (it, false);
7393 }
7394 }
7395 }
7396
7397 it->selective = old_selective;
7398 return newline_found_p;
7399 }
7400
7401
7402
7403
7404
7405
7406
7407 static void
7408 back_to_previous_visible_line_start (struct it *it)
7409 {
7410 while (IT_CHARPOS (*it) > BEGV)
7411 {
7412 back_to_previous_line_start (it);
7413
7414 if (IT_CHARPOS (*it) <= BEGV)
7415 break;
7416
7417
7418
7419 if (it->selective > 0
7420 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7421 it->selective))
7422 continue;
7423
7424
7425 {
7426 Lisp_Object prop;
7427 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7428 Qinvisible, it->window);
7429 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7430 continue;
7431 }
7432
7433 if (IT_CHARPOS (*it) <= BEGV)
7434 break;
7435
7436 {
7437 struct it it2;
7438 void *it2data = NULL;
7439 ptrdiff_t pos;
7440 ptrdiff_t beg, end;
7441 Lisp_Object val, overlay;
7442
7443 SAVE_IT (it2, *it, it2data);
7444
7445
7446 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7447 && beg < IT_CHARPOS (*it))
7448 goto replaced;
7449
7450
7451
7452 pos = --IT_CHARPOS (it2);
7453 --IT_BYTEPOS (it2);
7454 it2.sp = 0;
7455 bidi_unshelve_cache (NULL, false);
7456 it2.string_from_display_prop_p = false;
7457 it2.from_disp_prop_p = false;
7458 if (handle_display_prop (&it2) == HANDLED_RETURN
7459 && !NILP (val = get_char_property_and_overlay
7460 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7461 && (OVERLAYP (overlay)
7462 ? (beg = OVERLAY_START (overlay))
7463 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7464 {
7465 RESTORE_IT (it, it, it2data);
7466 goto replaced;
7467 }
7468
7469
7470 RESTORE_IT (it, it, it2data);
7471 break;
7472
7473 replaced:
7474 if (beg < BEGV)
7475 beg = BEGV;
7476 IT_CHARPOS (*it) = beg;
7477 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7478 }
7479 }
7480
7481 it->continuation_lines_width = 0;
7482
7483 eassert (IT_CHARPOS (*it) >= BEGV);
7484 eassert (it->medium_narrowing_begv > 0
7485 || IT_CHARPOS (*it) == BEGV
7486 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7487 CHECK_IT (it);
7488 }
7489
7490
7491
7492
7493
7494
7495
7496 void
7497 reseat_at_previous_visible_line_start (struct it *it)
7498 {
7499 back_to_previous_visible_line_start (it);
7500 reseat (it, it->current.pos, true);
7501 CHECK_IT (it);
7502 }
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512 static void
7513 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7514 {
7515 bool skipped_p = false;
7516 struct bidi_it bidi_it_prev;
7517 bool newline_found_p
7518 = forward_to_next_line_start (it, &skipped_p,
7519 on_newline_p ? &bidi_it_prev : NULL);
7520
7521
7522
7523 if (it->selective > 0)
7524 while (IT_CHARPOS (*it) < ZV
7525 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7526 it->selective))
7527 {
7528 eassert (IT_BYTEPOS (*it) == BEGV
7529 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7530 newline_found_p =
7531 forward_to_next_line_start (it, &skipped_p,
7532 on_newline_p ? &bidi_it_prev : NULL);
7533 }
7534
7535
7536 if (on_newline_p && newline_found_p)
7537 {
7538 if (STRINGP (it->string))
7539 {
7540 if (IT_STRING_CHARPOS (*it) > 0)
7541 {
7542 if (!it->bidi_p)
7543 {
7544 --IT_STRING_CHARPOS (*it);
7545 --IT_STRING_BYTEPOS (*it);
7546 }
7547 else
7548 {
7549
7550
7551
7552 it->bidi_it = bidi_it_prev;
7553 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7554 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7555 }
7556 }
7557 }
7558 else if (IT_CHARPOS (*it) > BEGV)
7559 {
7560 if (!it->bidi_p)
7561 {
7562 --IT_CHARPOS (*it);
7563 --IT_BYTEPOS (*it);
7564 }
7565 else
7566 {
7567
7568
7569 it->bidi_it = bidi_it_prev;
7570 IT_CHARPOS (*it) = it->bidi_it.charpos;
7571 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7572 }
7573 reseat (it, it->current.pos, false);
7574 }
7575 }
7576 else if (skipped_p)
7577 reseat (it, it->current.pos, false);
7578
7579 CHECK_IT (it);
7580 }
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593 static void
7594 reseat (struct it *it, struct text_pos pos, bool force_p)
7595 {
7596 ptrdiff_t original_pos = IT_CHARPOS (*it);
7597
7598 reseat_1 (it, pos, false);
7599
7600 if (current_buffer->long_line_optimizations_p)
7601 {
7602 if (!it->medium_narrowing_begv)
7603 {
7604 it->medium_narrowing_begv
7605 = get_medium_narrowing_begv (it->w, window_point (it->w));
7606 it->medium_narrowing_zv
7607 = get_medium_narrowing_zv (it->w, window_point (it->w));
7608 it->large_narrowing_begv
7609 = get_large_narrowing_begv (window_point (it->w));
7610 it->large_narrowing_zv
7611 = get_large_narrowing_zv (window_point (it->w));
7612 }
7613 else if ((pos.charpos < it->medium_narrowing_begv
7614 || pos.charpos > it->medium_narrowing_zv)
7615 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7616 {
7617 it->medium_narrowing_begv
7618 = get_medium_narrowing_begv (it->w, pos.charpos);
7619 it->medium_narrowing_zv
7620 = get_medium_narrowing_zv (it->w, pos.charpos);
7621 it->large_narrowing_begv
7622 = get_large_narrowing_begv (window_point (it->w));
7623 it->large_narrowing_zv
7624 = get_large_narrowing_zv (window_point (it->w));
7625 }
7626 }
7627
7628
7629
7630 if (force_p
7631 || CHARPOS (pos) > it->stop_charpos
7632 || CHARPOS (pos) < original_pos)
7633 {
7634 if (it->bidi_p)
7635 {
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646 if (CHARPOS (pos) != it->prev_stop)
7647 it->prev_stop = CHARPOS (pos);
7648 if (CHARPOS (pos) < it->base_level_stop)
7649 it->base_level_stop = 0;
7650 handle_stop (it);
7651 }
7652 else
7653 {
7654 handle_stop (it);
7655 it->prev_stop = it->base_level_stop = 0;
7656 }
7657
7658 }
7659
7660 CHECK_IT (it);
7661 }
7662
7663
7664
7665
7666
7667 static void
7668 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7669 {
7670
7671 eassert (it->s == NULL);
7672
7673
7674 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7675
7676 it->current.pos = it->position = pos;
7677 it->end_charpos = ZV;
7678 it->dpvec = NULL;
7679 it->current.dpvec_index = -1;
7680 it->current.overlay_string_index = -1;
7681 IT_STRING_CHARPOS (*it) = -1;
7682 IT_STRING_BYTEPOS (*it) = -1;
7683 it->string = Qnil;
7684 it->method = GET_FROM_BUFFER;
7685 it->object = it->w->contents;
7686 it->area = TEXT_AREA;
7687 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7688 it->sp = 0;
7689 it->string_from_display_prop_p = false;
7690 it->string_from_prefix_prop_p = false;
7691
7692 it->from_disp_prop_p = false;
7693 it->face_before_selective_p = false;
7694 if (it->bidi_p)
7695 {
7696 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7697 &it->bidi_it);
7698 bidi_unshelve_cache (NULL, false);
7699 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7700 it->bidi_it.string.s = NULL;
7701 it->bidi_it.string.lstring = Qnil;
7702 it->bidi_it.string.bufpos = 0;
7703 it->bidi_it.string.from_disp_str = false;
7704 it->bidi_it.string.unibyte = false;
7705 it->bidi_it.w = it->w;
7706 }
7707
7708 if (set_stop_p)
7709 {
7710 it->stop_charpos = CHARPOS (pos);
7711 it->base_level_stop = CHARPOS (pos);
7712 }
7713
7714 it->cmp_it.id = -1;
7715 it->min_width_property = Qnil;
7716 }
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737 static void
7738 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7739 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7740 int multibyte)
7741 {
7742
7743 it->stop_charpos = -1;
7744
7745
7746 memset (&it->current, 0, sizeof it->current);
7747 it->current.overlay_string_index = -1;
7748 it->current.dpvec_index = -1;
7749 eassert (charpos >= 0);
7750
7751
7752
7753 if (multibyte >= 0)
7754 it->multibyte_p = multibyte > 0;
7755
7756
7757
7758
7759
7760 it->bidi_p =
7761 !redisplay__inhibit_bidi
7762 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7763
7764 if (s == NULL)
7765 {
7766 eassert (STRINGP (string));
7767 it->string = string;
7768 it->s = NULL;
7769 it->end_charpos = it->string_nchars = SCHARS (string);
7770 it->method = GET_FROM_STRING;
7771 it->current.string_pos = string_pos (charpos, string);
7772
7773 if (it->bidi_p)
7774 {
7775 it->bidi_it.string.lstring = string;
7776 it->bidi_it.string.s = NULL;
7777 it->bidi_it.string.schars = it->end_charpos;
7778 it->bidi_it.string.bufpos = 0;
7779 it->bidi_it.string.from_disp_str = false;
7780 it->bidi_it.string.unibyte = !it->multibyte_p;
7781 it->bidi_it.w = it->w;
7782 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7783 FRAME_WINDOW_P (it->f), &it->bidi_it);
7784 }
7785 }
7786 else
7787 {
7788 it->s = (const unsigned char *) s;
7789 it->string = Qnil;
7790
7791
7792
7793 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7794 if (it->multibyte_p)
7795 {
7796 it->current.pos = c_string_pos (charpos, s, true);
7797 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7798 }
7799 else
7800 {
7801 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7802 it->end_charpos = it->string_nchars = strlen (s);
7803 }
7804
7805 if (it->bidi_p)
7806 {
7807 it->bidi_it.string.lstring = Qnil;
7808 it->bidi_it.string.s = (const unsigned char *) s;
7809 it->bidi_it.string.schars = it->end_charpos;
7810 it->bidi_it.string.bufpos = 0;
7811 it->bidi_it.string.from_disp_str = false;
7812 it->bidi_it.string.unibyte = !it->multibyte_p;
7813 it->bidi_it.w = it->w;
7814 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7815 &it->bidi_it);
7816 }
7817 it->method = GET_FROM_C_STRING;
7818 }
7819
7820
7821
7822 if (precision > 0 && it->end_charpos - charpos > precision)
7823 {
7824 it->end_charpos = it->string_nchars = charpos + precision;
7825 if (it->bidi_p)
7826 it->bidi_it.string.schars = it->end_charpos;
7827 }
7828
7829
7830
7831
7832
7833 if (field_width < 0)
7834 field_width = DISP_INFINITY;
7835
7836
7837
7838 if (field_width > it->end_charpos - charpos)
7839 it->end_charpos = charpos + field_width;
7840
7841
7842 if (DISP_TABLE_P (Vstandard_display_table))
7843 it->dp = XCHAR_TABLE (Vstandard_display_table);
7844
7845 it->stop_charpos = charpos;
7846 it->prev_stop = charpos;
7847 it->base_level_stop = 0;
7848 if (it->bidi_p)
7849 {
7850 it->bidi_it.first_elt = true;
7851 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7852 it->bidi_it.disp_pos = -1;
7853 }
7854 if (s == NULL && it->multibyte_p)
7855 {
7856 ptrdiff_t endpos = SCHARS (it->string);
7857 if (endpos > it->end_charpos)
7858 endpos = it->end_charpos;
7859 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7860 it->string, true);
7861 }
7862 CHECK_IT (it);
7863 }
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873 typedef bool (*next_element_function) (struct it *);
7874
7875 static next_element_function const get_next_element[NUM_IT_METHODS] =
7876 {
7877 next_element_from_buffer,
7878 next_element_from_display_vector,
7879 next_element_from_string,
7880 next_element_from_c_string,
7881 next_element_from_image,
7882 next_element_from_stretch,
7883 next_element_from_xwidget,
7884 };
7885
7886 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7898 ((IT)->cmp_it.id >= 0 \
7899 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7900 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7901 END_CHARPOS, (IT)->w, \
7902 (IT)->bidi_p \
7903 ? (IT)->bidi_it.resolved_level \
7904 : -1, \
7905 FACE_FROM_ID_OR_NULL ((IT)->f, \
7906 (IT)->face_id), \
7907 (IT)->string)))
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917 Lisp_Object
7918 lookup_glyphless_char_display (int c, struct it *it)
7919 {
7920 Lisp_Object glyphless_method = Qnil;
7921
7922 if (CHAR_TABLE_P (Vglyphless_char_display)
7923 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7924 {
7925 if (c >= 0)
7926 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7927 else
7928 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7929
7930 if (CONSP (glyphless_method))
7931 glyphless_method = FRAME_WINDOW_P (it->f)
7932 ? XCAR (glyphless_method)
7933 : XCDR (glyphless_method);
7934 }
7935
7936 retry:
7937 if (NILP (glyphless_method))
7938 {
7939 if (c >= 0)
7940
7941 return Qnil;
7942
7943 glyphless_method = Qempty_box;
7944 }
7945 if (EQ (glyphless_method, Qzero_width))
7946 {
7947 if (c >= 0)
7948 return glyphless_method;
7949
7950 glyphless_method = Qempty_box;
7951 }
7952 if (EQ (glyphless_method, Qthin_space))
7953 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7954 else if (EQ (glyphless_method, Qempty_box))
7955 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7956 else if (EQ (glyphless_method, Qhex_code))
7957 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7958 else if (STRINGP (glyphless_method))
7959 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7960 else
7961 {
7962
7963 glyphless_method = Qnil;
7964 goto retry;
7965 }
7966 it->what = IT_GLYPHLESS;
7967 return glyphless_method;
7968 }
7969
7970
7971
7972 static struct frame *last_escape_glyph_frame = NULL;
7973 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7974 static int last_escape_glyph_merged_face_id = 0;
7975
7976 static int
7977 merge_escape_glyph_face (struct it *it)
7978 {
7979 int face_id;
7980
7981 if (it->f == last_escape_glyph_frame
7982 && it->face_id == last_escape_glyph_face_id)
7983 face_id = last_escape_glyph_merged_face_id;
7984 else
7985 {
7986
7987 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
7988 last_escape_glyph_frame = it->f;
7989 last_escape_glyph_face_id = it->face_id;
7990 last_escape_glyph_merged_face_id = face_id;
7991 }
7992 return face_id;
7993 }
7994
7995
7996
7997 static struct frame *last_glyphless_glyph_frame = NULL;
7998 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
7999 static int last_glyphless_glyph_merged_face_id = 0;
8000
8001 int
8002 merge_glyphless_glyph_face (struct it *it)
8003 {
8004 int face_id;
8005
8006 if (it->f == last_glyphless_glyph_frame
8007 && it->face_id == last_glyphless_glyph_face_id)
8008 face_id = last_glyphless_glyph_merged_face_id;
8009 else
8010 {
8011
8012 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
8013 last_glyphless_glyph_frame = it->f;
8014 last_glyphless_glyph_face_id = it->face_id;
8015 last_glyphless_glyph_merged_face_id = face_id;
8016 }
8017 return face_id;
8018 }
8019
8020
8021
8022
8023 void
8024 forget_escape_and_glyphless_faces (void)
8025 {
8026 last_escape_glyph_frame = NULL;
8027 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8028 last_glyphless_glyph_frame = NULL;
8029 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8030 }
8031
8032
8033
8034
8035
8036 static bool
8037 get_next_display_element (struct it *it)
8038 {
8039
8040
8041
8042
8043 bool success_p;
8044
8045 get_next:
8046 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8047
8048 if (it->what == IT_CHARACTER)
8049 {
8050
8051
8052
8053
8054
8055 if (it->bidi_p && it->bidi_it.type == STRONG_R
8056 && !inhibit_bidi_mirroring)
8057 it->c = bidi_mirror_char (it->c);
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067 if (success_p && it->dpvec == NULL)
8068 {
8069 Lisp_Object dv;
8070 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8071 bool nonascii_space_p = false;
8072 bool nonascii_hyphen_p = false;
8073 int c = it->c;
8074
8075 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8076 {
8077 eassert (SINGLE_BYTE_CHAR_P (c));
8078 if (unibyte_display_via_language_environment)
8079 {
8080 c = DECODE_CHAR (unibyte, c);
8081 if (c < 0)
8082 c = BYTE8_TO_CHAR (it->c);
8083 }
8084 else
8085 c = BYTE8_TO_CHAR (it->c);
8086 }
8087
8088 if (it->dp
8089 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8090 VECTORP (dv)))
8091 {
8092 struct Lisp_Vector *v = XVECTOR (dv);
8093
8094
8095
8096
8097 if (v->header.size)
8098 {
8099 it->dpvec_char_len = it->len;
8100 it->dpvec = v->contents;
8101 it->dpend = v->contents + v->header.size;
8102 it->current.dpvec_index = 0;
8103 it->dpvec_face_id = -1;
8104 it->saved_face_id = it->face_id;
8105 it->method = GET_FROM_DISPLAY_VECTOR;
8106 it->ellipsis_p = false;
8107 }
8108 else
8109 {
8110 set_iterator_to_next (it, false);
8111 }
8112 goto get_next;
8113 }
8114
8115 if (! NILP (lookup_glyphless_char_display (c, it)))
8116 {
8117 if (it->what == IT_GLYPHLESS)
8118 goto done;
8119
8120 set_iterator_to_next (it, false);
8121 goto get_next;
8122 }
8123
8124
8125
8126 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8127 {
8128 if (blankp (c))
8129 nonascii_space_p = true;
8130 else if (c == SOFT_HYPHEN || c == HYPHEN
8131 || c == NON_BREAKING_HYPHEN)
8132 nonascii_hyphen_p = true;
8133 }
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146 if (((c < ' ' || c == 127)
8147 ? (it->area != TEXT_AREA
8148
8149 || (c != '\t'
8150 && it->glyph_row
8151 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8152 || (c != '\n' && c != '\t'))
8153 : (nonascii_space_p
8154 || nonascii_hyphen_p
8155 || CHAR_BYTE8_P (c)
8156 || ! CHAR_PRINTABLE_P (c))))
8157 {
8158
8159
8160
8161
8162
8163
8164 Lisp_Object gc;
8165 int ctl_len;
8166 int face_id;
8167 int lface_id = 0;
8168 int escape_glyph;
8169
8170
8171
8172 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8173 {
8174 int g;
8175
8176 g = '^';
8177
8178 if (it->dp
8179 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8180 {
8181 g = GLYPH_CODE_CHAR (gc);
8182 lface_id = GLYPH_CODE_FACE (gc);
8183 }
8184
8185 face_id = (lface_id
8186 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8187 : merge_escape_glyph_face (it));
8188
8189 XSETINT (it->ctl_chars[0], g);
8190 XSETINT (it->ctl_chars[1], c ^ 0100);
8191 ctl_len = 2;
8192 goto display_control;
8193 }
8194
8195
8196
8197
8198 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8199 {
8200
8201 face_id = merge_faces (it->w, Qnobreak_space, 0,
8202 it->face_id);
8203 XSETINT (it->ctl_chars[0],
8204 nobreak_char_ascii_display ? ' ' : it->c);
8205 ctl_len = 1;
8206 goto display_control;
8207 }
8208
8209
8210
8211
8212 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8213 {
8214
8215 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8216 it->face_id);
8217 XSETINT (it->ctl_chars[0],
8218 nobreak_char_ascii_display ? '-' : it->c);
8219 ctl_len = 1;
8220 goto display_control;
8221 }
8222
8223
8224
8225
8226 escape_glyph = '\\';
8227
8228 if (it->dp
8229 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8230 {
8231 escape_glyph = GLYPH_CODE_CHAR (gc);
8232 lface_id = GLYPH_CODE_FACE (gc);
8233 }
8234
8235 face_id = (lface_id
8236 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8237 : merge_escape_glyph_face (it));
8238
8239
8240
8241 if (nonascii_space_p || nonascii_hyphen_p)
8242 {
8243 XSETINT (it->ctl_chars[0], escape_glyph);
8244 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8245 ctl_len = 2;
8246 goto display_control;
8247 }
8248
8249 {
8250 char str[10];
8251 int len, i;
8252
8253 if (CHAR_BYTE8_P (c))
8254
8255 c = CHAR_TO_BYTE8 (c);
8256 const char *format_string = display_raw_bytes_as_hex
8257 ? "x%02x"
8258 : "%03o";
8259 len = sprintf (str, format_string, c + 0u);
8260
8261 XSETINT (it->ctl_chars[0], escape_glyph);
8262 for (i = 0; i < len; i++)
8263 XSETINT (it->ctl_chars[i + 1], str[i]);
8264 ctl_len = len + 1;
8265 }
8266
8267 display_control:
8268
8269 it->dpvec_char_len = it->len;
8270 it->dpvec = it->ctl_chars;
8271 it->dpend = it->dpvec + ctl_len;
8272 it->current.dpvec_index = 0;
8273 it->dpvec_face_id = face_id;
8274 it->saved_face_id = it->face_id;
8275 it->method = GET_FROM_DISPLAY_VECTOR;
8276 it->ellipsis_p = false;
8277 goto get_next;
8278 }
8279 it->char_to_display = c;
8280 }
8281 else if (success_p)
8282 {
8283 it->char_to_display = it->c;
8284 }
8285 }
8286
8287 #ifdef HAVE_WINDOW_SYSTEM
8288
8289
8290 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8291 && it->multibyte_p
8292 && success_p
8293 && FRAME_WINDOW_P (it->f))
8294 {
8295 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8296
8297 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8298 {
8299
8300 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8301
8302 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8303 }
8304 else
8305 {
8306 ptrdiff_t pos = (it->s ? -1
8307 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8308 : IT_CHARPOS (*it));
8309 int c;
8310
8311 if (it->what == IT_CHARACTER)
8312 c = it->char_to_display;
8313 else
8314 {
8315 struct composition *cmp = composition_table[it->cmp_it.id];
8316 int i;
8317
8318 c = ' ';
8319 for (i = 0; i < cmp->glyph_len; i++)
8320
8321
8322 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8323 break;
8324 }
8325 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8326 }
8327 }
8328 #endif
8329
8330 done:
8331
8332
8333 if (it->face_box_p
8334 && it->s == NULL)
8335 {
8336 if (it->method == GET_FROM_STRING && it->sp)
8337 {
8338 int face_id = underlying_face_id (it);
8339 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8340
8341 if (face)
8342 {
8343 if (face->box == FACE_NO_BOX)
8344 {
8345
8346
8347 int string_face_id = face_after_it_pos (it);
8348 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8349 it->end_of_box_run_p = true;
8350 }
8351
8352
8353
8354 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8355
8356
8357
8358 || (it->what == IT_COMPOSITION
8359 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8360 >= SCHARS (it->string))))
8361
8362
8363 && ((it->current.overlay_string_index >= 0
8364 && (it->current.overlay_string_index
8365 == it->n_overlay_strings - 1))
8366
8367 || it->from_disp_prop_p))
8368 {
8369 ptrdiff_t ignore;
8370 int next_face_id;
8371 bool text_from_string = false;
8372
8373
8374 struct text_pos pos = it->current.pos;
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386 if (it->from_disp_prop_p)
8387 {
8388 int stackp = it->sp - 1;
8389
8390
8391 while (stackp >= 0
8392 && STRINGP ((it->stack + stackp)->string))
8393 stackp--;
8394 if (stackp < 0)
8395 {
8396
8397
8398
8399
8400
8401
8402 text_from_string = true;
8403 pos = it->stack[it->sp - 1].position;
8404 }
8405 else
8406 pos = (it->stack + stackp)->position;
8407 }
8408 else
8409 INC_TEXT_POS (pos, it->multibyte_p);
8410
8411 if (text_from_string)
8412 {
8413 Lisp_Object base_string = it->stack[it->sp - 1].string;
8414
8415 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8416 it->end_of_box_run_p = true;
8417 else
8418 {
8419 next_face_id
8420 = face_at_string_position (it->w, base_string,
8421 CHARPOS (pos), 0,
8422 &ignore, face_id,
8423 false, 0);
8424 if (FACE_FROM_ID (it->f, next_face_id)->box
8425 == FACE_NO_BOX)
8426 it->end_of_box_run_p = true;
8427 }
8428 }
8429 else if (CHARPOS (pos) >= ZV)
8430 it->end_of_box_run_p = true;
8431 else
8432 {
8433 next_face_id =
8434 face_at_buffer_position (it->w, CHARPOS (pos),
8435 &ignore,
8436 CHARPOS (pos)
8437 + TEXT_PROP_DISTANCE_LIMIT,
8438 false, -1, 0);
8439 if (FACE_FROM_ID (it->f, next_face_id)->box
8440 == FACE_NO_BOX)
8441 it->end_of_box_run_p = true;
8442 }
8443 }
8444 }
8445 }
8446
8447
8448 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8449 {
8450 int face_id = face_after_it_pos (it);
8451 if (face_id != it->face_id
8452 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8453 it->end_of_box_run_p = true;
8454 }
8455 }
8456
8457
8458
8459
8460
8461 if (!success_p && it->sp > 0)
8462 {
8463 set_iterator_to_next (it, false);
8464 success_p = get_next_display_element (it);
8465 }
8466
8467
8468 return success_p;
8469 }
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487 void
8488 set_iterator_to_next (struct it *it, bool reseat_p)
8489 {
8490
8491 if (max_redisplay_ticks > 0)
8492 update_redisplay_ticks (1, it->w);
8493
8494 switch (it->method)
8495 {
8496 case GET_FROM_BUFFER:
8497
8498
8499
8500 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8501 reseat_at_next_visible_line_start (it, false);
8502 else if (it->cmp_it.id >= 0)
8503 {
8504
8505 if (! it->bidi_p)
8506 {
8507 IT_CHARPOS (*it) += it->cmp_it.nchars;
8508 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8509 }
8510 else
8511 {
8512 int i;
8513
8514
8515
8516
8517 for (i = 0; i < it->cmp_it.nchars; i++)
8518 bidi_move_to_visually_next (&it->bidi_it);
8519 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8520 IT_CHARPOS (*it) = it->bidi_it.charpos;
8521 }
8522
8523 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8524 && it->cmp_it.to < it->cmp_it.nglyphs)
8525 {
8526
8527
8528 it->cmp_it.from = it->cmp_it.to;
8529 }
8530 else if ((it->bidi_p && it->cmp_it.reversed_p)
8531 && it->cmp_it.from > 0)
8532 {
8533
8534
8535 it->cmp_it.to = it->cmp_it.from;
8536 }
8537 else
8538 {
8539
8540
8541 ptrdiff_t stop = it->end_charpos;
8542
8543 if (it->bidi_it.scan_dir < 0)
8544
8545
8546 stop = -1;
8547 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8548 IT_BYTEPOS (*it), stop, Qnil, true);
8549 }
8550 }
8551 else
8552 {
8553 eassert (it->len != 0);
8554
8555 if (!it->bidi_p)
8556 {
8557 IT_BYTEPOS (*it) += it->len;
8558 IT_CHARPOS (*it) += 1;
8559 }
8560 else
8561 {
8562 int prev_scan_dir = it->bidi_it.scan_dir;
8563
8564
8565 if (it->bidi_it.new_paragraph)
8566 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8567 false);
8568 bidi_move_to_visually_next (&it->bidi_it);
8569 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8570 IT_CHARPOS (*it) = it->bidi_it.charpos;
8571 if (prev_scan_dir != it->bidi_it.scan_dir)
8572 {
8573
8574
8575 ptrdiff_t stop = it->end_charpos;
8576 if (it->bidi_it.scan_dir < 0)
8577 stop = -1;
8578 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8579 IT_BYTEPOS (*it), stop, Qnil,
8580 true);
8581 }
8582 }
8583 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8584 }
8585 break;
8586
8587 case GET_FROM_C_STRING:
8588
8589 if (!it->bidi_p
8590
8591
8592
8593
8594 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8595 {
8596 IT_BYTEPOS (*it) += it->len;
8597 IT_CHARPOS (*it) += 1;
8598 }
8599 else
8600 {
8601 bidi_move_to_visually_next (&it->bidi_it);
8602 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8603 IT_CHARPOS (*it) = it->bidi_it.charpos;
8604 }
8605 break;
8606
8607 case GET_FROM_DISPLAY_VECTOR:
8608
8609
8610
8611
8612 ++it->current.dpvec_index;
8613
8614
8615
8616 it->face_id = it->saved_face_id;
8617
8618 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8619 {
8620 bool recheck_faces = it->ellipsis_p;
8621
8622 if (it->s)
8623 it->method = GET_FROM_C_STRING;
8624 else if (STRINGP (it->string))
8625 it->method = GET_FROM_STRING;
8626 else
8627 {
8628 it->method = GET_FROM_BUFFER;
8629 it->object = it->w->contents;
8630 }
8631
8632 it->dpvec = NULL;
8633 it->current.dpvec_index = -1;
8634
8635
8636 if (it->dpvec_char_len < 0)
8637 reseat_at_next_visible_line_start (it, true);
8638 else if (it->dpvec_char_len > 0)
8639 {
8640 it->len = it->dpvec_char_len;
8641 set_iterator_to_next (it, reseat_p);
8642 }
8643
8644
8645 if (recheck_faces)
8646 {
8647 if (it->method == GET_FROM_STRING)
8648 it->stop_charpos = IT_STRING_CHARPOS (*it);
8649 else
8650 it->stop_charpos = IT_CHARPOS (*it);
8651 }
8652 }
8653 break;
8654
8655 case GET_FROM_STRING:
8656
8657 eassert (it->s == NULL && STRINGP (it->string));
8658
8659
8660
8661
8662
8663 if (it->current.overlay_string_index >= 0)
8664 {
8665
8666
8667
8668 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8669 goto consider_string_end;
8670 }
8671 else
8672 {
8673
8674
8675 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8676 goto consider_string_end;
8677 }
8678 if (it->cmp_it.id >= 0)
8679 {
8680
8681
8682
8683 if (! it->bidi_p)
8684 {
8685 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8686 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8687 }
8688 else
8689 {
8690 int i;
8691
8692 for (i = 0; i < it->cmp_it.nchars; i++)
8693 bidi_move_to_visually_next (&it->bidi_it);
8694 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8695 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8696 }
8697
8698
8699
8700 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8701 && (it->cmp_it.to < it->cmp_it.nglyphs))
8702 {
8703
8704
8705 it->cmp_it.from = it->cmp_it.to;
8706 }
8707 else if ((it->bidi_p && it->cmp_it.reversed_p)
8708 && it->cmp_it.from > 0)
8709 {
8710
8711
8712 it->cmp_it.to = it->cmp_it.from;
8713 }
8714 else
8715 {
8716
8717
8718
8719
8720
8721
8722 ptrdiff_t stop = SCHARS (it->string);
8723
8724 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8725 stop = -1;
8726 else if (it->end_charpos < stop)
8727 {
8728
8729
8730
8731 stop = it->end_charpos;
8732 }
8733 composition_compute_stop_pos (&it->cmp_it,
8734 IT_STRING_CHARPOS (*it),
8735 IT_STRING_BYTEPOS (*it), stop,
8736 it->string, true);
8737 }
8738 }
8739 else
8740 {
8741 if (!it->bidi_p
8742
8743
8744
8745
8746
8747 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8748 {
8749 IT_STRING_BYTEPOS (*it) += it->len;
8750 IT_STRING_CHARPOS (*it) += 1;
8751 }
8752 else
8753 {
8754 int prev_scan_dir = it->bidi_it.scan_dir;
8755
8756 bidi_move_to_visually_next (&it->bidi_it);
8757 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8758 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8759
8760
8761 if (prev_scan_dir != it->bidi_it.scan_dir)
8762 {
8763 ptrdiff_t stop = SCHARS (it->string);
8764
8765 if (it->bidi_it.scan_dir < 0)
8766 stop = -1;
8767 else if (it->end_charpos < stop)
8768 stop = it->end_charpos;
8769
8770 composition_compute_stop_pos (&it->cmp_it,
8771 IT_STRING_CHARPOS (*it),
8772 IT_STRING_BYTEPOS (*it), stop,
8773 it->string, true);
8774 }
8775 }
8776 }
8777
8778 consider_string_end:
8779
8780 if (it->current.overlay_string_index >= 0)
8781 {
8782
8783
8784 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8785 {
8786 it->ellipsis_p = false;
8787 next_overlay_string (it);
8788 if (it->ellipsis_p)
8789 setup_for_ellipsis (it, 0);
8790 }
8791 }
8792 else
8793 {
8794
8795
8796
8797
8798 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8799 && it->sp > 0)
8800 {
8801 pop_it (it);
8802 if (it->method == GET_FROM_STRING)
8803 goto consider_string_end;
8804 }
8805 }
8806 break;
8807
8808 case GET_FROM_IMAGE:
8809 case GET_FROM_STRETCH:
8810 case GET_FROM_XWIDGET:
8811
8812
8813
8814
8815 eassert (it->sp > 0);
8816 pop_it (it);
8817 if (it->method == GET_FROM_STRING)
8818 goto consider_string_end;
8819 break;
8820
8821 default:
8822
8823 emacs_abort ();
8824 }
8825
8826 eassert (it->method != GET_FROM_STRING
8827 || (STRINGP (it->string)
8828 && IT_STRING_CHARPOS (*it) >= 0));
8829 }
8830
8831
8832
8833
8834
8835
8836
8837
8838
8839
8840 static bool
8841 next_element_from_display_vector (struct it *it)
8842 {
8843 Lisp_Object gc;
8844 int prev_face_id = it->face_id;
8845 int next_face_id;
8846
8847
8848 eassert (it->dpvec && it->current.dpvec_index >= 0);
8849
8850 it->face_id = it->saved_face_id;
8851
8852
8853
8854 if (it->dpend - it->dpvec > 0
8855 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8856 {
8857 struct face *this_face, *prev_face, *next_face;
8858
8859 it->c = GLYPH_CODE_CHAR (gc);
8860 it->len = CHAR_BYTES (it->c);
8861
8862
8863
8864
8865 if (it->dpvec_face_id >= 0)
8866 it->face_id = it->dpvec_face_id;
8867 else
8868 {
8869 int lface_id = GLYPH_CODE_FACE (gc);
8870 if (lface_id > 0)
8871 it->face_id = merge_faces (it->w, Qt, lface_id,
8872 it->saved_face_id);
8873 }
8874
8875
8876
8877
8878 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8879 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8880
8881
8882 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8883 && (!prev_face
8884 || prev_face->box == FACE_NO_BOX));
8885
8886
8887
8888
8889 next_face_id = it->saved_face_id;
8890 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8891 {
8892 if (it->dpvec_face_id >= 0)
8893 next_face_id = it->dpvec_face_id;
8894 else
8895 {
8896 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8897 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8898
8899 if (lface_id > 0)
8900 next_face_id = merge_faces (it->w, Qt, lface_id,
8901 it->saved_face_id);
8902 }
8903 }
8904 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8905 if (this_face && this_face->box != FACE_NO_BOX
8906 && (!next_face || next_face->box == FACE_NO_BOX))
8907 it->end_of_box_run_p = true;
8908 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8909 }
8910 else
8911
8912 it->c = ' ', it->len = 1;
8913
8914
8915
8916
8917 it->what = IT_CHARACTER;
8918 return true;
8919 }
8920
8921
8922
8923 static void
8924 get_visually_first_element (struct it *it)
8925 {
8926 bool string_p = STRINGP (it->string) || it->s;
8927 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8928 ptrdiff_t bob;
8929 ptrdiff_t obegv = BEGV;
8930
8931 SET_WITH_NARROWED_BEGV (it, bob,
8932 string_p ? 0 :
8933 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8934 it->medium_narrowing_begv);
8935
8936 if (STRINGP (it->string))
8937 {
8938 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8939 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8940 }
8941 else
8942 {
8943 it->bidi_it.charpos = IT_CHARPOS (*it);
8944 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8945 }
8946
8947 if (it->bidi_it.charpos == eob)
8948 {
8949
8950
8951
8952 it->bidi_it.first_elt = false;
8953 }
8954 else if (it->bidi_it.charpos == bob
8955 || (!string_p
8956 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8957 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8958 {
8959
8960
8961 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8962 bidi_move_to_visually_next (&it->bidi_it);
8963 }
8964 else
8965 {
8966 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8967
8968
8969
8970
8971 if (string_p)
8972 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8973 else
8974 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8975 find_newline_no_quit (IT_CHARPOS (*it),
8976 IT_BYTEPOS (*it), -1,
8977 &it->bidi_it.bytepos),
8978 it->medium_narrowing_begv);
8979 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8980 do
8981 {
8982
8983
8984 bidi_move_to_visually_next (&it->bidi_it);
8985 }
8986 while (it->bidi_it.bytepos != orig_bytepos
8987 && it->bidi_it.charpos < eob);
8988 }
8989
8990
8991 if (STRINGP (it->string))
8992 {
8993 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8994 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8995 }
8996 else
8997 {
8998 IT_CHARPOS (*it) = it->bidi_it.charpos;
8999 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
9000 }
9001
9002 if (STRINGP (it->string) || !it->s)
9003 {
9004 ptrdiff_t stop, charpos, bytepos;
9005
9006 if (STRINGP (it->string))
9007 {
9008 eassert (!it->s);
9009 stop = SCHARS (it->string);
9010 if (stop > it->end_charpos)
9011 stop = it->end_charpos;
9012 charpos = IT_STRING_CHARPOS (*it);
9013 bytepos = IT_STRING_BYTEPOS (*it);
9014 }
9015 else
9016 {
9017 stop = it->end_charpos;
9018 charpos = IT_CHARPOS (*it);
9019 bytepos = IT_BYTEPOS (*it);
9020 }
9021 if (it->bidi_it.scan_dir < 0)
9022 stop = -1;
9023 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9024 it->string, true);
9025 }
9026 }
9027
9028
9029
9030
9031
9032
9033 static bool
9034 next_element_from_string (struct it *it)
9035 {
9036 struct text_pos position;
9037
9038 eassert (STRINGP (it->string));
9039 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9040 eassert (IT_STRING_CHARPOS (*it) >= 0);
9041 position = it->current.string_pos;
9042
9043
9044
9045
9046
9047 if (it->bidi_p && it->bidi_it.first_elt)
9048 {
9049 get_visually_first_element (it);
9050 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9051 }
9052
9053
9054 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9055 {
9056 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9057 {
9058 if (!(!it->bidi_p
9059 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9060 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9061 {
9062
9063
9064
9065
9066
9067
9068 handle_stop_backwards (it, it->stop_charpos);
9069 return GET_NEXT_DISPLAY_ELEMENT (it);
9070 }
9071 else
9072 {
9073 if (it->bidi_p)
9074 {
9075
9076
9077 it->prev_stop = it->stop_charpos;
9078
9079
9080
9081 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9082 it->base_level_stop = it->stop_charpos;
9083 }
9084 handle_stop (it);
9085
9086
9087
9088 return GET_NEXT_DISPLAY_ELEMENT (it);
9089 }
9090 }
9091 else if (it->bidi_p
9092
9093
9094
9095 && IT_STRING_CHARPOS (*it) < it->prev_stop
9096
9097
9098
9099
9100 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9101 {
9102
9103
9104
9105
9106 if (it->base_level_stop <= 0
9107 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9108 it->base_level_stop = 0;
9109 handle_stop_backwards (it, it->base_level_stop);
9110 return GET_NEXT_DISPLAY_ELEMENT (it);
9111 }
9112 }
9113
9114 if (it->current.overlay_string_index >= 0)
9115 {
9116
9117
9118
9119 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9120 {
9121 it->what = IT_EOB;
9122 return false;
9123 }
9124 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9125 IT_STRING_BYTEPOS (*it),
9126 it->bidi_it.scan_dir < 0
9127 ? -1
9128 : SCHARS (it->string))
9129 && next_element_from_composition (it))
9130 {
9131 return true;
9132 }
9133 else if (STRING_MULTIBYTE (it->string))
9134 {
9135 const unsigned char *s = (SDATA (it->string)
9136 + IT_STRING_BYTEPOS (*it));
9137 it->c = check_char_and_length (s, &it->len);
9138 }
9139 else
9140 {
9141 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9142 it->len = 1;
9143 }
9144 }
9145 else
9146 {
9147
9148
9149
9150
9151 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9152 {
9153 it->what = IT_EOB;
9154 return false;
9155 }
9156 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9157 {
9158
9159 it->c = ' ', it->len = 1;
9160 CHARPOS (position) = BYTEPOS (position) = -1;
9161 }
9162 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9163 IT_STRING_BYTEPOS (*it),
9164 it->bidi_it.scan_dir < 0
9165 ? -1
9166 : it->string_nchars)
9167 && next_element_from_composition (it))
9168 {
9169 return true;
9170 }
9171 else if (STRING_MULTIBYTE (it->string))
9172 {
9173 const unsigned char *s = (SDATA (it->string)
9174 + IT_STRING_BYTEPOS (*it));
9175 it->c = check_char_and_length (s, &it->len);
9176 }
9177 else
9178 {
9179 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9180 it->len = 1;
9181 }
9182 }
9183
9184
9185 it->what = IT_CHARACTER;
9186 it->object = it->string;
9187 it->position = position;
9188 return true;
9189 }
9190
9191
9192
9193
9194
9195
9196
9197
9198
9199 static bool
9200 next_element_from_c_string (struct it *it)
9201 {
9202 bool success_p = true;
9203
9204 eassert (it->s);
9205 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9206 it->what = IT_CHARACTER;
9207 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9208 it->object = make_fixnum (0);
9209
9210
9211
9212
9213
9214 if (it->bidi_p && it->bidi_it.first_elt)
9215 get_visually_first_element (it);
9216
9217
9218
9219
9220 if (IT_CHARPOS (*it) >= it->end_charpos)
9221 {
9222
9223 it->what = IT_EOB;
9224 success_p = false;
9225 }
9226 else if (IT_CHARPOS (*it) >= it->string_nchars)
9227 {
9228
9229 it->c = ' ', it->len = 1;
9230 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9231 }
9232 else if (it->multibyte_p)
9233 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9234 else
9235 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9236
9237 return success_p;
9238 }
9239
9240
9241
9242
9243
9244
9245
9246 static bool
9247 next_element_from_ellipsis (struct it *it)
9248 {
9249 if (it->selective_display_ellipsis_p)
9250 setup_for_ellipsis (it, it->len);
9251 else
9252 {
9253
9254
9255
9256
9257 it->saved_face_id = it->face_id;
9258 it->method = GET_FROM_BUFFER;
9259 it->object = it->w->contents;
9260 reseat_at_next_visible_line_start (it, true);
9261 it->face_before_selective_p = true;
9262 }
9263
9264 return GET_NEXT_DISPLAY_ELEMENT (it);
9265 }
9266
9267
9268
9269
9270
9271
9272
9273 static bool
9274 next_element_from_image (struct it *it)
9275 {
9276 it->what = IT_IMAGE;
9277 return true;
9278 }
9279
9280 static bool
9281 next_element_from_xwidget (struct it *it)
9282 {
9283 it->what = IT_XWIDGET;
9284 return true;
9285 }
9286
9287
9288
9289
9290
9291
9292 static bool
9293 next_element_from_stretch (struct it *it)
9294 {
9295 it->what = IT_STRETCH;
9296 return true;
9297 }
9298
9299
9300
9301
9302
9303
9304 static void
9305 compute_stop_pos_backwards (struct it *it)
9306 {
9307 const int SCAN_BACK_LIMIT = 1000;
9308 struct text_pos pos;
9309 struct display_pos save_current = it->current;
9310 struct text_pos save_position = it->position;
9311 ptrdiff_t charpos = IT_CHARPOS (*it);
9312 ptrdiff_t where_we_are = charpos;
9313 ptrdiff_t save_stop_pos = it->stop_charpos;
9314 ptrdiff_t save_end_pos = it->end_charpos;
9315
9316 eassert (NILP (it->string) && !it->s);
9317 eassert (it->bidi_p);
9318 it->bidi_p = false;
9319 do
9320 {
9321 it->end_charpos = min (charpos + 1, ZV);
9322 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9323 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9324 reseat_1 (it, pos, false);
9325 compute_stop_pos (it);
9326
9327 if (it->stop_charpos <= charpos)
9328 emacs_abort ();
9329 }
9330 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9331
9332 if (it->stop_charpos <= where_we_are)
9333 it->prev_stop = it->stop_charpos;
9334 else
9335 it->prev_stop = BEGV;
9336 it->bidi_p = true;
9337 it->current = save_current;
9338 it->position = save_position;
9339 it->stop_charpos = save_stop_pos;
9340 it->end_charpos = save_end_pos;
9341 }
9342
9343
9344
9345
9346
9347
9348
9349
9350
9351 static void
9352 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9353 {
9354 bool bufp = !STRINGP (it->string);
9355 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9356 struct display_pos save_current = it->current;
9357 struct text_pos save_position = it->position;
9358 struct composition_it save_cmp_it = it->cmp_it;
9359 struct text_pos pos1;
9360 ptrdiff_t next_stop;
9361
9362
9363 eassert (it->bidi_p);
9364 it->bidi_p = false;
9365 do
9366 {
9367 it->prev_stop = charpos;
9368 if (bufp)
9369 {
9370 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9371 reseat_1 (it, pos1, false);
9372 }
9373 else
9374 it->current.string_pos = string_pos (charpos, it->string);
9375 compute_stop_pos (it);
9376
9377 if (it->stop_charpos <= it->prev_stop)
9378 emacs_abort ();
9379 charpos = it->stop_charpos;
9380 }
9381 while (charpos <= where_we_are);
9382
9383 it->bidi_p = true;
9384 it->current = save_current;
9385 it->position = save_position;
9386 it->cmp_it = save_cmp_it;
9387 next_stop = it->stop_charpos;
9388 it->stop_charpos = it->prev_stop;
9389 handle_stop (it);
9390 it->stop_charpos = next_stop;
9391 }
9392
9393
9394
9395
9396
9397
9398 static bool
9399 next_element_from_buffer (struct it *it)
9400 {
9401 bool success_p = true;
9402
9403 eassert (IT_CHARPOS (*it) >= BEGV);
9404 eassert (NILP (it->string) && !it->s);
9405 eassert (!it->bidi_p
9406 || (NILP (it->bidi_it.string.lstring)
9407 && it->bidi_it.string.s == NULL));
9408
9409
9410
9411
9412
9413 if (it->bidi_p && it->bidi_it.first_elt)
9414 {
9415 get_visually_first_element (it);
9416 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9417 }
9418
9419 if (IT_CHARPOS (*it) >= it->stop_charpos)
9420 {
9421 if (IT_CHARPOS (*it) >= it->end_charpos)
9422 {
9423 bool overlay_strings_follow_p;
9424
9425
9426
9427 if (it->overlay_strings_at_end_processed_p)
9428 overlay_strings_follow_p = false;
9429 else
9430 {
9431 it->overlay_strings_at_end_processed_p = true;
9432 overlay_strings_follow_p = get_overlay_strings (it, 0);
9433 }
9434
9435 if (overlay_strings_follow_p)
9436 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9437 else
9438 {
9439 it->what = IT_EOB;
9440 it->position = it->current.pos;
9441 success_p = false;
9442 }
9443 }
9444 else if (!(!it->bidi_p
9445 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9446 || IT_CHARPOS (*it) == it->stop_charpos))
9447 {
9448
9449
9450
9451
9452
9453
9454 handle_stop_backwards (it, it->stop_charpos);
9455 it->ignore_overlay_strings_at_pos_p = false;
9456 return GET_NEXT_DISPLAY_ELEMENT (it);
9457 }
9458 else
9459 {
9460 if (it->bidi_p)
9461 {
9462
9463
9464 it->prev_stop = it->stop_charpos;
9465
9466
9467
9468 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9469 it->base_level_stop = it->stop_charpos;
9470 }
9471 handle_stop (it);
9472 it->ignore_overlay_strings_at_pos_p = false;
9473 return GET_NEXT_DISPLAY_ELEMENT (it);
9474 }
9475 }
9476 else if (it->bidi_p
9477
9478
9479
9480 && IT_CHARPOS (*it) < it->prev_stop
9481
9482
9483
9484
9485 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9486 {
9487 if (it->base_level_stop <= 0
9488 || IT_CHARPOS (*it) < it->base_level_stop)
9489 {
9490
9491
9492
9493
9494 it->base_level_stop = BEGV;
9495 compute_stop_pos_backwards (it);
9496 handle_stop_backwards (it, it->prev_stop);
9497 }
9498 else
9499 handle_stop_backwards (it, it->base_level_stop);
9500 it->ignore_overlay_strings_at_pos_p = false;
9501 return GET_NEXT_DISPLAY_ELEMENT (it);
9502 }
9503 else
9504 {
9505
9506
9507 unsigned char *p;
9508 ptrdiff_t stop;
9509
9510
9511
9512 it->ignore_overlay_strings_at_pos_p = false;
9513
9514 if (composition_break_at_point
9515 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9516 && !NILP (Vauto_composition_mode))
9517 {
9518
9519 if (it->bidi_it.scan_dir < 0)
9520 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9521 else
9522 stop = (IT_CHARPOS (*it) < PT
9523 && PT < it->end_charpos) ? PT : it->end_charpos;
9524 }
9525 else
9526 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9527 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9528 stop)
9529 && next_element_from_composition (it))
9530 {
9531 return true;
9532 }
9533
9534
9535 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9536 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9537 it->c = string_char_and_length (p, &it->len);
9538 else
9539 it->c = *p, it->len = 1;
9540
9541
9542 it->what = IT_CHARACTER;
9543 it->object = it->w->contents;
9544 it->position = it->current.pos;
9545
9546
9547
9548 if (it->selective)
9549 {
9550 if (it->c == '\n')
9551 {
9552
9553
9554 if (it->selective > 0
9555 && IT_CHARPOS (*it) + 1 < ZV
9556 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9557 IT_BYTEPOS (*it) + 1,
9558 it->selective))
9559 {
9560 success_p = next_element_from_ellipsis (it);
9561 it->dpvec_char_len = -1;
9562 }
9563 }
9564 else if (it->c == '\r' && it->selective == -1)
9565 {
9566
9567
9568
9569 success_p = next_element_from_ellipsis (it);
9570 it->dpvec_char_len = -1;
9571 }
9572 }
9573 }
9574
9575
9576 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9577 return success_p;
9578 }
9579
9580
9581
9582
9583
9584
9585
9586 static bool
9587 next_element_from_composition (struct it *it)
9588 {
9589 it->what = IT_COMPOSITION;
9590 it->len = it->cmp_it.nbytes;
9591 if (STRINGP (it->string))
9592 {
9593 if (it->c < 0)
9594 {
9595 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9596 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9597 return false;
9598 }
9599 it->position = it->current.string_pos;
9600 it->object = it->string;
9601 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9602 IT_STRING_BYTEPOS (*it), it->string);
9603 }
9604 else
9605 {
9606 if (it->c < 0)
9607 {
9608 IT_CHARPOS (*it) += it->cmp_it.nchars;
9609 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9610 if (it->bidi_p)
9611 {
9612 if (it->bidi_it.new_paragraph)
9613 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9614 false);
9615
9616
9617 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9618 bidi_move_to_visually_next (&it->bidi_it);
9619 }
9620 return false;
9621 }
9622 it->position = it->current.pos;
9623 it->object = it->w->contents;
9624 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9625 IT_BYTEPOS (*it), Qnil);
9626 }
9627 return true;
9628 }
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9640 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676 static enum move_it_result
9677 move_it_in_display_line_to (struct it *it,
9678 ptrdiff_t to_charpos, int to_x,
9679 enum move_operation_enum op)
9680 {
9681 enum move_it_result result = MOVE_UNDEFINED;
9682 struct glyph_row *saved_glyph_row;
9683 struct it wrap_it, atpos_it, atx_it, ppos_it;
9684 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9685 void *ppos_data = NULL;
9686 bool may_wrap = false;
9687 enum it_method prev_method = it->method;
9688 ptrdiff_t closest_pos UNINIT;
9689 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9690 bool saw_smaller_pos = prev_pos < to_charpos;
9691 bool line_number_pending = false;
9692
9693
9694 saved_glyph_row = it->glyph_row;
9695 it->glyph_row = NULL;
9696
9697
9698
9699
9700
9701
9702 wrap_it.sp = -1;
9703 atpos_it.sp = -1;
9704 atx_it.sp = -1;
9705
9706
9707
9708
9709
9710
9711
9712
9713 if (it->bidi_p)
9714 {
9715 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9716 {
9717 SAVE_IT (ppos_it, *it, ppos_data);
9718 closest_pos = IT_CHARPOS (*it);
9719 }
9720 else
9721 closest_pos = ZV;
9722 }
9723
9724 #define BUFFER_POS_REACHED_P() \
9725 ((op & MOVE_TO_POS) != 0 \
9726 && BUFFERP (it->object) \
9727 && (IT_CHARPOS (*it) == to_charpos \
9728 || ((!it->bidi_p \
9729 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9730 && IT_CHARPOS (*it) > to_charpos) \
9731 || (it->what == IT_COMPOSITION \
9732 && ((IT_CHARPOS (*it) > to_charpos \
9733 && to_charpos >= it->cmp_it.charpos) \
9734 || (IT_CHARPOS (*it) < to_charpos \
9735 && to_charpos <= it->cmp_it.charpos)))) \
9736 && (it->method == GET_FROM_BUFFER \
9737 || (it->method == GET_FROM_DISPLAY_VECTOR \
9738 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9739
9740 if (it->hpos == 0)
9741 {
9742
9743
9744
9745
9746 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9747 && should_produce_line_number (it))
9748 {
9749 if (it->current_x == it->first_visible_x)
9750 maybe_produce_line_number (it);
9751 else
9752 line_number_pending = true;
9753 }
9754
9755 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9756 handle_line_prefix (it);
9757 }
9758
9759 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9760 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9761
9762 while (true)
9763 {
9764 int x, i, ascent = 0, descent = 0;
9765
9766
9767 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9768 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9769 (IT)->max_descent = descent)
9770
9771
9772
9773 if ((op & MOVE_TO_POS) != 0
9774 && BUFFERP (it->object)
9775 && it->method == GET_FROM_BUFFER
9776 && (((!it->bidi_p
9777
9778
9779
9780
9781 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9782 && IT_CHARPOS (*it) > to_charpos)
9783 || (it->bidi_p
9784 && (prev_method == GET_FROM_IMAGE
9785 || prev_method == GET_FROM_STRETCH
9786 || prev_method == GET_FROM_STRING)
9787
9788 && ((prev_pos < to_charpos
9789 && IT_CHARPOS (*it) >= to_charpos)
9790
9791 || (prev_pos > to_charpos
9792 && IT_CHARPOS (*it) <= to_charpos)))))
9793 {
9794 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9795 {
9796 result = MOVE_POS_MATCH_OR_ZV;
9797 break;
9798 }
9799 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9800
9801
9802
9803 SAVE_IT (atpos_it, *it, atpos_data);
9804 }
9805
9806
9807
9808
9809
9810 if (!get_next_display_element (it))
9811 {
9812 result = MOVE_POS_MATCH_OR_ZV;
9813 break;
9814 }
9815
9816 if (it->line_wrap == TRUNCATE)
9817 {
9818
9819
9820
9821
9822
9823
9824 if (BUFFER_POS_REACHED_P ()
9825 && (it->pixel_width > 0
9826 || IT_CHARPOS (*it) > to_charpos
9827 || it->area != TEXT_AREA))
9828 {
9829 result = MOVE_POS_MATCH_OR_ZV;
9830 break;
9831 }
9832 }
9833 else
9834 {
9835 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9836 {
9837 bool next_may_wrap = may_wrap;
9838
9839 if (char_can_wrap_after (it))
9840 next_may_wrap = true;
9841 else
9842 next_may_wrap = false;
9843
9844 if (may_wrap && char_can_wrap_before (it))
9845 {
9846
9847
9848
9849
9850
9851 if (atpos_it.sp >= 0)
9852 {
9853 RESTORE_IT (it, &atpos_it, atpos_data);
9854 result = MOVE_POS_MATCH_OR_ZV;
9855 goto done;
9856 }
9857 if (atx_it.sp >= 0)
9858 {
9859 RESTORE_IT (it, &atx_it, atx_data);
9860 result = MOVE_X_REACHED;
9861 goto done;
9862 }
9863
9864 SAVE_IT (wrap_it, *it, wrap_data);
9865 }
9866
9867 may_wrap = next_may_wrap;
9868 }
9869 }
9870
9871
9872
9873 ascent = it->max_ascent;
9874 descent = it->max_descent;
9875
9876
9877
9878
9879
9880 x = it->current_x;
9881
9882 PRODUCE_GLYPHS (it);
9883
9884 if (it->area != TEXT_AREA)
9885 {
9886 prev_method = it->method;
9887 if (it->method == GET_FROM_BUFFER)
9888 prev_pos = IT_CHARPOS (*it);
9889 set_iterator_to_next (it, true);
9890 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9891 SET_TEXT_POS (this_line_min_pos,
9892 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9893 if (it->bidi_p
9894 && (op & MOVE_TO_POS)
9895 && IT_CHARPOS (*it) > to_charpos
9896 && IT_CHARPOS (*it) < closest_pos)
9897 closest_pos = IT_CHARPOS (*it);
9898 continue;
9899 }
9900
9901
9902
9903
9904
9905
9906
9907
9908
9909
9910
9911
9912
9913
9914
9915
9916
9917
9918
9919 if (it->nglyphs)
9920 {
9921
9922
9923 int single_glyph_width = it->pixel_width / it->nglyphs;
9924 int new_x;
9925 int x_before_this_char = x;
9926 int hpos_before_this_char = it->hpos;
9927
9928 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9929 {
9930 new_x = x + single_glyph_width;
9931
9932
9933 if ((op & MOVE_TO_X) && new_x > to_x)
9934 {
9935 if (BUFFER_POS_REACHED_P ())
9936 {
9937 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9938 goto buffer_pos_reached;
9939 if (atpos_it.sp < 0)
9940 {
9941 SAVE_IT (atpos_it, *it, atpos_data);
9942 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9943 }
9944 }
9945 else
9946 {
9947 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9948 {
9949 it->current_x = x;
9950 result = MOVE_X_REACHED;
9951 break;
9952 }
9953 if (atx_it.sp < 0)
9954 {
9955 SAVE_IT (atx_it, *it, atx_data);
9956 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9957 }
9958 }
9959 }
9960
9961 if (
9962 it->line_wrap != TRUNCATE
9963 && (
9964 new_x > it->last_visible_x
9965
9966
9967 || (new_x == it->last_visible_x
9968 && FRAME_WINDOW_P (it->f)
9969 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9970 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9971 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9972 {
9973 bool moved_forward = false;
9974
9975 if (
9976
9977 it->hpos == 0
9978 || (new_x == it->last_visible_x
9979 && FRAME_WINDOW_P (it->f)))
9980 {
9981 ++it->hpos;
9982 it->current_x = new_x;
9983
9984
9985
9986 if (i == it->nglyphs - 1)
9987 {
9988
9989
9990
9991 if (BUFFER_POS_REACHED_P ())
9992 {
9993 bool can_wrap = true;
9994
9995
9996
9997
9998
9999 if (it->line_wrap == WORD_WRAP
10000 && wrap_it.sp >= 0
10001 && may_wrap
10002 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10003 {
10004 struct it tem_it;
10005 void *tem_data = NULL;
10006
10007 SAVE_IT (tem_it, *it, tem_data);
10008 set_iterator_to_next (it, true);
10009 if (get_next_display_element (it)
10010 && !char_can_wrap_before (it))
10011 can_wrap = false;
10012 RESTORE_IT (it, &tem_it, tem_data);
10013 }
10014 if (it->line_wrap != WORD_WRAP
10015 || wrap_it.sp < 0
10016
10017
10018
10019
10020
10021
10022
10023 || (may_wrap && can_wrap
10024 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10025 {
10026 it->hpos = hpos_before_this_char;
10027 it->current_x = x_before_this_char;
10028 result = MOVE_POS_MATCH_OR_ZV;
10029 break;
10030 }
10031 if (it->line_wrap == WORD_WRAP
10032 && atpos_it.sp < 0)
10033 {
10034 SAVE_IT (atpos_it, *it, atpos_data);
10035 atpos_it.current_x = x_before_this_char;
10036 atpos_it.hpos = hpos_before_this_char;
10037 }
10038 }
10039
10040 prev_method = it->method;
10041 if (it->method == GET_FROM_BUFFER)
10042 prev_pos = IT_CHARPOS (*it);
10043 set_iterator_to_next (it, true);
10044 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10045 SET_TEXT_POS (this_line_min_pos,
10046 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10047
10048
10049
10050
10051
10052
10053
10054 if (!FRAME_WINDOW_P (it->f)
10055 || ((it->bidi_p
10056 && it->bidi_it.paragraph_dir == R2L)
10057 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10058 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10059 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10060 {
10061 if (!get_next_display_element (it))
10062 {
10063 result = MOVE_POS_MATCH_OR_ZV;
10064 break;
10065 }
10066 moved_forward = true;
10067 if (BUFFER_POS_REACHED_P ())
10068 {
10069 if (ITERATOR_AT_END_OF_LINE_P (it))
10070 result = MOVE_POS_MATCH_OR_ZV;
10071 else
10072 result = MOVE_LINE_CONTINUED;
10073 break;
10074 }
10075 if (ITERATOR_AT_END_OF_LINE_P (it)
10076 && (it->line_wrap != WORD_WRAP
10077 || wrap_it.sp < 0
10078 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10079 {
10080 result = MOVE_NEWLINE_OR_CR;
10081 break;
10082 }
10083 }
10084 }
10085 }
10086 else
10087 IT_RESET_X_ASCENT_DESCENT (it);
10088
10089
10090
10091
10092
10093
10094 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10095
10096
10097
10098
10099
10100 && (!moved_forward || char_can_wrap_before (it)))
10101 {
10102
10103
10104 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10105 && atx_it.sp >= 0)
10106 {
10107 RESTORE_IT (it, &atx_it, atx_data);
10108 atpos_it.sp = -1;
10109 atx_it.sp = -1;
10110 result = MOVE_X_REACHED;
10111 break;
10112 }
10113 }
10114 else if (wrap_it.sp >= 0)
10115 {
10116 RESTORE_IT (it, &wrap_it, wrap_data);
10117 atpos_it.sp = -1;
10118 atx_it.sp = -1;
10119 }
10120
10121 move_trace ("move_it_in: continued at %td\n",
10122 IT_CHARPOS (*it));
10123 result = MOVE_LINE_CONTINUED;
10124 break;
10125 }
10126
10127 if (BUFFER_POS_REACHED_P ())
10128 {
10129 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10130 goto buffer_pos_reached;
10131 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10132 {
10133 SAVE_IT (atpos_it, *it, atpos_data);
10134 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10135 }
10136 }
10137
10138 if (new_x > it->first_visible_x)
10139 {
10140
10141
10142 if (line_number_pending)
10143 {
10144 line_number_pending = false;
10145 it->current_x = it->first_visible_x;
10146 maybe_produce_line_number (it);
10147 it->current_x += new_x - it->first_visible_x;
10148 }
10149
10150
10151 ++it->hpos;
10152 }
10153 }
10154
10155 if (result != MOVE_UNDEFINED)
10156 break;
10157 }
10158 else if (BUFFER_POS_REACHED_P ())
10159 {
10160 buffer_pos_reached:
10161 IT_RESET_X_ASCENT_DESCENT (it);
10162 result = MOVE_POS_MATCH_OR_ZV;
10163 break;
10164 }
10165 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10166 {
10167
10168
10169
10170
10171 eassert (it->nglyphs == 0);
10172 result = MOVE_X_REACHED;
10173 break;
10174 }
10175
10176
10177 if (ITERATOR_AT_END_OF_LINE_P (it))
10178 {
10179
10180
10181
10182
10183 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10184 {
10185 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10186 {
10187 if (closest_pos < ZV)
10188 {
10189 RESTORE_IT (it, &ppos_it, ppos_data);
10190
10191
10192 if (closest_pos != to_charpos)
10193 move_it_in_display_line_to (it, closest_pos, -1,
10194 MOVE_TO_POS);
10195 result = MOVE_POS_MATCH_OR_ZV;
10196 }
10197 else
10198 goto buffer_pos_reached;
10199 }
10200 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10201 && IT_CHARPOS (*it) > to_charpos)
10202 goto buffer_pos_reached;
10203 else
10204 result = MOVE_NEWLINE_OR_CR;
10205 }
10206 else
10207 result = MOVE_NEWLINE_OR_CR;
10208
10209
10210
10211
10212 if (it->line_wrap == TRUNCATE
10213 && it->current_x <= it->first_visible_x
10214 && result == MOVE_NEWLINE_OR_CR
10215 && it->char_to_display == '\n')
10216 {
10217 it->max_ascent = it->ascent;
10218 it->max_descent = it->descent;
10219 }
10220
10221
10222
10223 if (result == MOVE_NEWLINE_OR_CR)
10224 it->constrain_row_ascent_descent_p = false;
10225 break;
10226 }
10227
10228 prev_method = it->method;
10229 if (it->method == GET_FROM_BUFFER)
10230 prev_pos = IT_CHARPOS (*it);
10231
10232
10233
10234
10235
10236
10237
10238
10239
10240 bool overwide_wrap_prefix =
10241 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10242 && it->sp > 0 && it->method == GET_FROM_STRETCH
10243 && it->current_x >= it->last_visible_x
10244 && it->continuation_lines_width > 0
10245 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10246
10247
10248 if (!overwide_wrap_prefix)
10249 set_iterator_to_next (it, true);
10250 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10251 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10252 if (IT_CHARPOS (*it) < to_charpos)
10253 saw_smaller_pos = true;
10254 if (it->bidi_p
10255 && (op & MOVE_TO_POS)
10256 && IT_CHARPOS (*it) >= to_charpos
10257 && IT_CHARPOS (*it) < closest_pos)
10258 closest_pos = IT_CHARPOS (*it);
10259
10260
10261
10262 if (it->line_wrap == TRUNCATE
10263 && it->current_x >= it->last_visible_x)
10264 {
10265 if (!FRAME_WINDOW_P (it->f)
10266 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10267 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10268 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10269 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10270 {
10271 bool at_eob_p = false;
10272
10273 if ((at_eob_p = !get_next_display_element (it))
10274 || BUFFER_POS_REACHED_P ()
10275
10276
10277
10278
10279 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10280 && !saw_smaller_pos
10281 && IT_CHARPOS (*it) > to_charpos))
10282 {
10283 if (it->bidi_p
10284 && !BUFFER_POS_REACHED_P ()
10285 && !at_eob_p && closest_pos < ZV)
10286 {
10287 RESTORE_IT (it, &ppos_it, ppos_data);
10288 if (closest_pos != to_charpos)
10289 move_it_in_display_line_to (it, closest_pos, -1,
10290 MOVE_TO_POS);
10291 }
10292 result = MOVE_POS_MATCH_OR_ZV;
10293 break;
10294 }
10295 if (ITERATOR_AT_END_OF_LINE_P (it))
10296 {
10297 result = MOVE_NEWLINE_OR_CR;
10298 break;
10299 }
10300 }
10301 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10302 && !saw_smaller_pos
10303 && IT_CHARPOS (*it) > to_charpos)
10304 {
10305 if (closest_pos < ZV)
10306 {
10307 RESTORE_IT (it, &ppos_it, ppos_data);
10308 if (closest_pos != to_charpos)
10309 move_it_in_display_line_to (it, closest_pos, -1,
10310 MOVE_TO_POS);
10311 }
10312 result = MOVE_POS_MATCH_OR_ZV;
10313 break;
10314 }
10315 result = MOVE_LINE_TRUNCATED;
10316 break;
10317 }
10318 #undef IT_RESET_X_ASCENT_DESCENT
10319 }
10320
10321 #undef BUFFER_POS_REACHED_P
10322
10323
10324
10325
10326
10327
10328 if (result == MOVE_LINE_CONTINUED
10329 && it->line_wrap == WORD_WRAP
10330 && wrap_it.sp >= 0
10331 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10332 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10333 RESTORE_IT (it, &wrap_it, wrap_data);
10334 else if (atpos_it.sp >= 0)
10335 RESTORE_IT (it, &atpos_it, atpos_data);
10336 else if (atx_it.sp >= 0)
10337 RESTORE_IT (it, &atx_it, atx_data);
10338
10339 done:
10340
10341 if (atpos_data)
10342 bidi_unshelve_cache (atpos_data, true);
10343 if (atx_data)
10344 bidi_unshelve_cache (atx_data, true);
10345 if (wrap_data)
10346 bidi_unshelve_cache (wrap_data, true);
10347 if (ppos_data)
10348 bidi_unshelve_cache (ppos_data, true);
10349
10350
10351
10352 it->glyph_row = saved_glyph_row;
10353 return result;
10354 }
10355
10356
10357 void
10358 move_it_in_display_line (struct it *it,
10359 ptrdiff_t to_charpos, int to_x,
10360 enum move_operation_enum op)
10361 {
10362 if (it->line_wrap == WORD_WRAP
10363 && (op & MOVE_TO_X))
10364 {
10365 struct it save_it;
10366 void *save_data = NULL;
10367 int skip;
10368
10369 SAVE_IT (save_it, *it, save_data);
10370 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10371
10372
10373
10374
10375 if (skip == MOVE_LINE_CONTINUED)
10376 {
10377 int prev_x = max (it->current_x - 1, 0);
10378 RESTORE_IT (it, &save_it, save_data);
10379 move_it_in_display_line_to
10380 (it, -1, prev_x, MOVE_TO_X);
10381 }
10382 else
10383 bidi_unshelve_cache (save_data, true);
10384 }
10385 else
10386 move_it_in_display_line_to (it, to_charpos, to_x, op);
10387 }
10388
10389
10390
10391
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403
10404 int
10405 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10406 {
10407 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10408 int line_height, line_start_x = 0, reached = 0;
10409 int max_current_x = 0;
10410 void *backup_data = NULL;
10411 ptrdiff_t orig_charpos = -1;
10412 enum it_method orig_method = NUM_IT_METHODS;
10413
10414 for (;;)
10415 {
10416 orig_charpos = IT_CHARPOS (*it);
10417 orig_method = it->method;
10418 if (op & MOVE_TO_VPOS)
10419 {
10420
10421
10422 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10423 {
10424 if (it->vpos == to_vpos)
10425 {
10426 reached = 1;
10427 break;
10428 }
10429 else
10430 skip = move_it_in_display_line_to (it, -1, -1, 0);
10431 }
10432 else
10433 {
10434
10435
10436 if (it->vpos == to_vpos)
10437 {
10438 reached = 2;
10439 break;
10440 }
10441
10442 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10443
10444 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10445 {
10446 reached = 3;
10447 break;
10448 }
10449 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10450 {
10451
10452 skip = move_it_in_display_line_to (it, to_charpos,
10453 -1, MOVE_TO_POS);
10454 if (skip == MOVE_POS_MATCH_OR_ZV)
10455 {
10456 reached = 4;
10457 break;
10458 }
10459 }
10460 }
10461 }
10462 else if (op & MOVE_TO_Y)
10463 {
10464 struct it it_backup;
10465
10466 if (it->line_wrap == WORD_WRAP)
10467 SAVE_IT (it_backup, *it, backup_data);
10468
10469
10470
10471
10472
10473
10474
10475
10476
10477
10478
10479
10480
10481 skip = move_it_in_display_line_to
10482 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10483 (MOVE_TO_X | (op & MOVE_TO_POS)));
10484
10485
10486 if (skip == MOVE_POS_MATCH_OR_ZV)
10487 reached = 5;
10488 else if (skip == MOVE_X_REACHED)
10489 {
10490
10491
10492
10493
10494 line_height = it->max_ascent + it->max_descent;
10495 if (to_y >= it->current_y
10496 && to_y < it->current_y + line_height)
10497 {
10498 reached = 6;
10499 break;
10500 }
10501 SAVE_IT (it_backup, *it, backup_data);
10502 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10503 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10504 op & MOVE_TO_POS);
10505 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10506 line_height = it->max_ascent + it->max_descent;
10507 move_trace ("move_it: line_height = %d\n", line_height);
10508
10509 if (to_y >= it->current_y
10510 && to_y < it->current_y + line_height)
10511 {
10512
10513
10514
10515
10516
10517
10518
10519
10520 int max_ascent = it->max_ascent;
10521 int max_descent = it->max_descent;
10522
10523 RESTORE_IT (it, &it_backup, backup_data);
10524 it->max_ascent = max_ascent;
10525 it->max_descent = max_descent;
10526 reached = 6;
10527 }
10528 else
10529 {
10530 skip = skip2;
10531 if (skip == MOVE_POS_MATCH_OR_ZV)
10532 {
10533 reached = 7;
10534
10535
10536
10537
10538
10539
10540
10541 if (to_charpos > 0
10542 && IT_CHARPOS (*it) != to_charpos
10543 && ((IT_CHARPOS (it_backup) > to_charpos)
10544 == (IT_CHARPOS (*it) > to_charpos)))
10545 {
10546 int max_ascent = it->max_ascent;
10547 int max_descent = it->max_descent;
10548
10549 RESTORE_IT (it, &it_backup, backup_data);
10550 it->max_ascent = max_ascent;
10551 it->max_descent = max_descent;
10552 }
10553 }
10554 }
10555 }
10556 else
10557 {
10558
10559 line_height = it->max_ascent + it->max_descent;
10560 move_trace ("move_it: line_height = %d\n", line_height);
10561
10562 if (to_y >= it->current_y
10563 && to_y < it->current_y + line_height)
10564 {
10565 if (to_y > it->current_y)
10566 max_current_x = max (it->current_x, max_current_x);
10567
10568
10569
10570
10571
10572 if (skip == MOVE_LINE_CONTINUED
10573 && it->line_wrap == WORD_WRAP)
10574 {
10575 int prev_x = max (it->current_x - 1, 0);
10576 RESTORE_IT (it, &it_backup, backup_data);
10577 skip = move_it_in_display_line_to
10578 (it, -1, prev_x, MOVE_TO_X);
10579 }
10580
10581 reached = 6;
10582 }
10583 }
10584
10585 if (reached)
10586 {
10587 max_current_x = max (it->current_x, max_current_x);
10588 break;
10589 }
10590 }
10591 else if (BUFFERP (it->object)
10592 && (it->method == GET_FROM_BUFFER
10593 || it->method == GET_FROM_STRETCH)
10594 && IT_CHARPOS (*it) >= to_charpos
10595
10596
10597
10598
10599
10600 && !(it->bidi_p
10601 && it->bidi_it.scan_dir == -1))
10602 skip = MOVE_POS_MATCH_OR_ZV;
10603 else
10604 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10605
10606 switch (skip)
10607 {
10608 case MOVE_POS_MATCH_OR_ZV:
10609 max_current_x = max (it->current_x, max_current_x);
10610 reached = 8;
10611 goto out;
10612
10613 case MOVE_NEWLINE_OR_CR:
10614 max_current_x = max (it->current_x, max_current_x);
10615 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10616 it->override_ascent = -1;
10617 set_iterator_to_next (it, true);
10618 it->continuation_lines_width = 0;
10619 break;
10620
10621 case MOVE_LINE_TRUNCATED:
10622 max_current_x = it->last_visible_x;
10623 it->continuation_lines_width = 0;
10624 reseat_at_next_visible_line_start (it, false);
10625 if ((op & MOVE_TO_POS) != 0
10626 && (IT_CHARPOS (*it) > to_charpos
10627 || (IT_CHARPOS (*it) == to_charpos
10628
10629
10630 && to_charpos == ZV
10631 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10632
10633
10634
10635 && (it->sp == 0
10636 || (STRINGP (it->string)
10637 && (it->current.overlay_string_index < 0
10638 || (it->current.overlay_string_index >= 0
10639 && it->current.overlay_string_index
10640 >= it->n_overlay_strings - 1))
10641 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10642 {
10643 reached = 9;
10644 goto out;
10645 }
10646 break;
10647
10648 case MOVE_LINE_CONTINUED:
10649 max_current_x = it->last_visible_x;
10650
10651
10652
10653
10654 if (it->c == '\t')
10655 {
10656 it->continuation_lines_width += it->last_visible_x;
10657
10658
10659
10660 if (it->current_x != it->last_visible_x
10661 && (op & MOVE_TO_VPOS)
10662 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10663 {
10664 line_start_x = it->current_x + it->pixel_width
10665 - it->last_visible_x;
10666 if (FRAME_WINDOW_P (it->f))
10667 {
10668 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10669 struct font *face_font = face->font;
10670
10671
10672
10673
10674
10675
10676
10677 eassert (face_font);
10678 if (face_font)
10679 {
10680 if (line_start_x < face_font->space_width)
10681 line_start_x
10682 += it->tab_width * face_font->space_width;
10683 }
10684 }
10685 set_iterator_to_next (it, false);
10686 }
10687 }
10688 else
10689 {
10690
10691
10692
10693
10694
10695
10696
10697
10698 if (IT_CHARPOS (*it) == orig_charpos
10699 && it->method == orig_method
10700 && orig_method == GET_FROM_BUFFER)
10701 set_iterator_to_next (it, false);
10702 it->continuation_lines_width += it->current_x;
10703 }
10704 break;
10705
10706 default:
10707 emacs_abort ();
10708 }
10709
10710
10711 it->current_x = line_start_x;
10712 line_start_x = 0;
10713 it->hpos = 0;
10714 it->line_number_produced_p = false;
10715 it->current_y += it->max_ascent + it->max_descent;
10716 ++it->vpos;
10717 last_height = it->max_ascent + it->max_descent;
10718 it->max_ascent = it->max_descent = 0;
10719 }
10720
10721 out:
10722
10723
10724
10725
10726
10727
10728 if (!FRAME_WINDOW_P (it->f)
10729 && op & MOVE_TO_POS
10730 && IT_CHARPOS (*it) == to_charpos
10731 && it->what == IT_CHARACTER
10732 && it->nglyphs > 1
10733 && it->line_wrap == WINDOW_WRAP
10734 && it->current_x == it->last_visible_x - 1
10735 && it->c != '\n'
10736 && it->c != '\t'
10737 && it->w->window_end_valid
10738 && it->vpos < it->w->window_end_vpos)
10739 {
10740 it->continuation_lines_width += it->current_x;
10741 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10742 it->current_y += it->max_ascent + it->max_descent;
10743 ++it->vpos;
10744 last_height = it->max_ascent + it->max_descent;
10745 }
10746
10747 if (backup_data)
10748 bidi_unshelve_cache (backup_data, true);
10749
10750 move_trace ("move_it_to: reached %d\n", reached);
10751
10752 return max_current_x;
10753 }
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765 void
10766 move_it_vertically_backward (struct it *it, int dy)
10767 {
10768 int nlines, h;
10769 struct it it2, it3;
10770 void *it2data = NULL, *it3data = NULL;
10771 ptrdiff_t start_pos;
10772 int nchars_per_row
10773 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10774 ptrdiff_t pos_limit;
10775
10776 move_further_back:
10777 eassert (dy >= 0);
10778
10779 start_pos = IT_CHARPOS (*it);
10780
10781
10782 nlines = max (1, dy / default_line_pixel_height (it->w));
10783 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10784 pos_limit = BEGV;
10785 else
10786 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10787
10788
10789
10790
10791 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10792 back_to_previous_visible_line_start (it);
10793
10794
10795
10796
10797
10798 reseat_1 (it, it->current.pos, true);
10799
10800
10801 it->current_x = it->hpos = 0;
10802
10803 it->continuation_lines_width = 0;
10804
10805
10806
10807
10808
10809 SAVE_IT (it2, *it, it2data);
10810 it2.max_ascent = it2.max_descent = 0;
10811 do
10812 {
10813 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10814 MOVE_TO_POS | MOVE_TO_VPOS);
10815 }
10816 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10817
10818
10819
10820
10821
10822
10823 || (it2.method == GET_FROM_STRING
10824 && IT_CHARPOS (it2) == start_pos
10825 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10826 eassert (IT_CHARPOS (*it) >= BEGV);
10827 SAVE_IT (it3, it2, it3data);
10828
10829 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10830 eassert (IT_CHARPOS (*it) >= BEGV);
10831
10832
10833 h = it2.current_y - it->current_y;
10834
10835 nlines = it2.vpos - it->vpos;
10836
10837
10838
10839 it->vpos -= nlines;
10840 it->current_y -= h;
10841
10842 if (dy == 0)
10843 {
10844
10845
10846
10847 RESTORE_IT (it, it, it2data);
10848 if (nlines > 0)
10849 move_it_by_lines (it, nlines);
10850
10851
10852
10853
10854
10855
10856 if (it->bidi_p
10857 && !it->continuation_lines_width
10858 && !STRINGP (it->string)
10859 && IT_CHARPOS (*it) > BEGV
10860 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10861 {
10862 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10863
10864 dec_both (&cp, &bp);
10865 SET_WITH_NARROWED_BEGV (it, cp,
10866 find_newline_no_quit (cp, bp, -1, NULL),
10867 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10868 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10869 }
10870 bidi_unshelve_cache (it3data, true);
10871 }
10872 else
10873 {
10874
10875
10876 int target_y = it->current_y + h - dy;
10877 int y0 = it3.current_y;
10878 int y1;
10879 int line_height;
10880
10881 RESTORE_IT (&it3, &it3, it3data);
10882 y1 = line_bottom_y (&it3);
10883 line_height = y1 - y0;
10884 RESTORE_IT (it, it, it2data);
10885
10886
10887 if (target_y < it->current_y
10888
10889
10890
10891
10892 && (it->current_y - target_y
10893 > min (window_box_height (it->w), line_height * 2 / 3))
10894 && IT_CHARPOS (*it) > BEGV)
10895 {
10896 move_trace (" not far enough -> move_vert %d\n",
10897 target_y - it->current_y);
10898 dy = it->current_y - target_y;
10899 goto move_further_back;
10900 }
10901 else if (target_y >= it->current_y + line_height
10902 && IT_CHARPOS (*it) < ZV)
10903 {
10904
10905
10906
10907
10908
10909
10910
10911
10912 if (!FRAME_WINDOW_P (it->f))
10913 move_it_vertically (it, target_y - it->current_y);
10914 else
10915 {
10916 struct text_pos last_pos;
10917 int last_y, last_vpos;
10918 do
10919 {
10920 last_pos = it->current.pos;
10921 last_y = it->current_y;
10922 last_vpos = it->vpos;
10923 move_it_by_lines (it, 1);
10924 }
10925 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10926 if (it->current_y > target_y)
10927 {
10928 reseat (it, last_pos, true);
10929 it->current_y = last_y;
10930 it->vpos = last_vpos;
10931 }
10932 }
10933 }
10934 }
10935 }
10936
10937
10938
10939
10940
10941
10942 void
10943 move_it_vertically (struct it *it, int dy)
10944 {
10945 if (dy <= 0)
10946 move_it_vertically_backward (it, -dy);
10947 else
10948 {
10949 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10950 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10951 MOVE_TO_POS | MOVE_TO_Y);
10952 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10953
10954
10955
10956 if (IT_CHARPOS (*it) == ZV
10957 && ZV > BEGV
10958 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10959 move_it_by_lines (it, 0);
10960 }
10961 }
10962
10963
10964
10965
10966 void
10967 move_it_past_eol (struct it *it)
10968 {
10969 enum move_it_result rc;
10970
10971 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10972 if (rc == MOVE_NEWLINE_OR_CR)
10973 set_iterator_to_next (it, false);
10974 }
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985 void
10986 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10987 {
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005 if (dvpos == 0)
11006 {
11007
11008 move_it_vertically_backward (it, 0);
11009
11010 last_height = 0;
11011 }
11012 else if (dvpos > 0)
11013 {
11014 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
11015 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11016 {
11017
11018
11019
11020
11021
11022
11023
11024
11025
11026
11027 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11028 -1, -1, -1, MOVE_TO_POS);
11029 }
11030 }
11031 else
11032 {
11033 struct it it2;
11034 void *it2data = NULL;
11035 ptrdiff_t start_charpos, orig_charpos, i;
11036 int nchars_per_row
11037 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11038 bool hit_pos_limit = false;
11039 ptrdiff_t pos_limit;
11040
11041
11042
11043
11044 dvpos += it->vpos;
11045 orig_charpos = IT_CHARPOS (*it);
11046 move_it_vertically_backward (it, 0);
11047 dvpos -= it->vpos;
11048
11049
11050
11051 start_charpos = IT_CHARPOS (*it);
11052 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11053 pos_limit = BEGV;
11054 else
11055 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11056
11057 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11058 back_to_previous_visible_line_start (it);
11059 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11060 hit_pos_limit = true;
11061 reseat (it, it->current.pos, true);
11062
11063
11064 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11065 {
11066
11067 dvpos += it->vpos;
11068 move_it_vertically_backward (it, 0);
11069 dvpos -= it->vpos;
11070 if (IT_POS_VALID_AFTER_MOVE_P (it))
11071 break;
11072
11073
11074 back_to_previous_visible_line_start (it);
11075 reseat (it, it->current.pos, true);
11076 dvpos--;
11077 }
11078
11079 it->current_x = it->hpos = 0;
11080
11081
11082
11083 SAVE_IT (it2, *it, it2data);
11084 it2.vpos = it2.current_y = 0;
11085 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11086 it->vpos -= it2.vpos;
11087 it->current_y -= it2.current_y;
11088 it->current_x = it->hpos = 0;
11089
11090
11091 if (it2.vpos > -dvpos)
11092 {
11093 int delta = it2.vpos + dvpos;
11094
11095 RESTORE_IT (&it2, &it2, it2data);
11096 SAVE_IT (it2, *it, it2data);
11097 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11098
11099
11100 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11101 RESTORE_IT (it, &it2, it2data);
11102 else
11103 bidi_unshelve_cache (it2data, true);
11104 }
11105 else if (hit_pos_limit && pos_limit > BEGV
11106 && dvpos < 0 && it2.vpos < -dvpos)
11107 {
11108
11109
11110
11111
11112
11113
11114
11115
11116 dvpos += it2.vpos;
11117 RESTORE_IT (it, it, it2data);
11118 for (i = -dvpos; i > 0; --i)
11119 {
11120 back_to_previous_visible_line_start (it);
11121 it->vpos--;
11122 }
11123 reseat_1 (it, it->current.pos, true);
11124 }
11125 else
11126 RESTORE_IT (it, it, it2data);
11127 }
11128 }
11129
11130 int
11131 partial_line_height (struct it *it_origin)
11132 {
11133
11134
11135
11136
11137
11138 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11139 && it_origin->line_wrap == TRUNCATE)
11140 return 0;
11141
11142 int partial_height;
11143 void *it_data = NULL;
11144 struct it it;
11145 SAVE_IT (it, *it_origin, it_data);
11146 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11147 MOVE_TO_POS | MOVE_TO_Y);
11148 if (it.what == IT_EOB)
11149 {
11150 int vis_height = it.last_visible_y - it.current_y;
11151 int height = it.ascent + it.descent;
11152 partial_height = (vis_height < height) ? vis_height : 0;
11153 }
11154 else
11155 {
11156 int last_line_y = it.current_y;
11157 move_it_by_lines (&it, 1);
11158 partial_height = (it.current_y > it.last_visible_y)
11159 ? it.last_visible_y - last_line_y : 0;
11160 }
11161 RESTORE_IT (&it, &it, it_data);
11162 return partial_height;
11163 }
11164
11165
11166
11167
11168
11169
11170
11171
11172
11173
11174
11175
11176 static enum move_it_result
11177 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11178 {
11179 ptrdiff_t nl_bytepos;
11180 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11181 1, &nl_bytepos);
11182 struct text_pos new_pos;
11183 enum move_it_result move_result;
11184
11185 if (nl_pos - IT_CHARPOS (*it) > nchars)
11186 {
11187 SET_TEXT_POS (new_pos,
11188 IT_CHARPOS (*it) + nchars,
11189 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11190 move_result = MOVE_X_REACHED;
11191 }
11192 else
11193 {
11194 if (nl_bytepos < ZV_BYTE
11195 || (nl_bytepos > BEGV_BYTE
11196 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11197 {
11198 nl_pos--;
11199 nl_bytepos--;
11200 move_result = MOVE_NEWLINE_OR_CR;
11201 }
11202 else
11203 move_result = MOVE_POS_MATCH_OR_ZV;
11204 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11205 }
11206 reseat (it, new_pos, false);
11207 return move_result;
11208 }
11209
11210
11211
11212 bool
11213 in_display_vector_p (struct it *it)
11214 {
11215 return (it->method == GET_FROM_DISPLAY_VECTOR
11216 && it->current.dpvec_index > 0
11217 && it->dpvec + it->current.dpvec_index != it->dpend);
11218 }
11219
11220
11221
11222
11223
11224 static Lisp_Object
11225 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11226 Lisp_Object x_limit, Lisp_Object y_limit,
11227 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11228 {
11229 struct window *w = decode_live_window (window);
11230 struct it it;
11231 ptrdiff_t start, end, bpos;
11232 struct text_pos startp;
11233 void *itdata = NULL;
11234 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11235
11236 if (NILP (from))
11237 {
11238 start = BEGV;
11239 bpos = BEGV_BYTE;
11240 }
11241 else if (EQ (from, Qt))
11242 {
11243 start = BEGV;
11244 bpos = BEGV_BYTE;
11245 while (bpos < ZV_BYTE)
11246 {
11247 c = FETCH_BYTE (bpos);
11248 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11249 break;
11250 inc_both (&start, &bpos);
11251 }
11252 while (bpos > BEGV_BYTE)
11253 {
11254 dec_both (&start, &bpos);
11255 c = FETCH_BYTE (bpos);
11256 if (!(c == ' ' || c == '\t'))
11257 break;
11258 }
11259 }
11260 else if (CONSP (from))
11261 {
11262 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11263 bpos = CHAR_TO_BYTE (start);
11264 CHECK_FIXNUM (XCDR (from));
11265 vertical_offset = XFIXNUM (XCDR (from));
11266 }
11267 else
11268 {
11269 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11270 bpos = CHAR_TO_BYTE (start);
11271 }
11272
11273 SET_TEXT_POS (startp, start, bpos);
11274
11275 if (NILP (to))
11276 end = ZV;
11277 else if (EQ (to, Qt))
11278 {
11279 end = ZV;
11280 bpos = ZV_BYTE;
11281 while (bpos > BEGV_BYTE)
11282 {
11283 dec_both (&end, &bpos);
11284 c = FETCH_BYTE (bpos);
11285 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11286 {
11287 inc_both (&end, &bpos);
11288 break;
11289 }
11290 }
11291 while (bpos < ZV_BYTE)
11292 {
11293 c = fetch_char_advance (&end, &bpos);
11294 if (!(c == ' ' || c == '\t'))
11295 break;
11296 }
11297 }
11298 else
11299 end = clip_to_bounds (start, fix_position (to), ZV);
11300
11301 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11302 max_x = XFIXNUM (x_limit);
11303 else if (!NILP (x_limit))
11304 max_x = INT_MAX;
11305
11306 if (NILP (y_limit))
11307 max_y = INT_MAX;
11308 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11309 max_y = XFIXNUM (y_limit);
11310
11311 itdata = bidi_shelve_cache ();
11312
11313 start_display (&it, w, startp);
11314
11315 int start_y = it.current_y;
11316
11317
11318
11319
11320
11321
11322
11323 it.bidi_p = false;
11324
11325 int start_x;
11326 if (vertical_offset != 0)
11327 {
11328 int last_y;
11329 it.current_y = 0;
11330
11331 move_it_by_lines (&it, 0);
11332
11333
11334
11335
11336
11337 if (vertical_offset < 0)
11338 {
11339 while (it.current_y > vertical_offset)
11340 {
11341 last_y = it.current_y;
11342 move_it_vertically_backward (&it,
11343 (abs (vertical_offset)
11344 + it.current_y));
11345
11346 if (it.current_y == last_y)
11347 break;
11348 }
11349 }
11350 else
11351 {
11352 move_it_vertically (&it, vertical_offset);
11353 }
11354
11355 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11356 + WINDOW_HEADER_LINE_HEIGHT (w));
11357 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11358 start_y = it.current_y;
11359 start_x = it.current_x;
11360 }
11361 else
11362 {
11363
11364
11365
11366 reseat_at_previous_visible_line_start (&it);
11367 it.current_x = it.hpos = 0;
11368 if (IT_CHARPOS (it) != start)
11369 {
11370 void *it1data = NULL;
11371 struct it it1;
11372
11373 SAVE_IT (it1, it, it1data);
11374 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11375
11376
11377
11378
11379
11380 if (IT_CHARPOS (it) > start && start > BEGV)
11381 {
11382 ptrdiff_t it1pos = IT_CHARPOS (it1);
11383 int it1_x = it1.current_x;
11384
11385 RESTORE_IT (&it, &it1, it1data);
11386
11387
11388
11389
11390
11391 if (start - 1 > it1pos)
11392 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11393 else
11394 move_it_in_display_line (&it, start, it1_x + 1,
11395 MOVE_TO_POS | MOVE_TO_X);
11396 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11397 start_x = it.current_x;
11398
11399
11400
11401 if (IT_CHARPOS (it) == start - 1)
11402 start_x += it.pixel_width;
11403 }
11404 else
11405 {
11406 start_x = it.current_x;
11407 bidi_unshelve_cache (it1data, true);
11408 }
11409 }
11410 else
11411 start_x = it.current_x;
11412 }
11413
11414
11415 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11416 int to_x = -1;
11417 it.current_y = start_y;
11418
11419
11420 if (FETCH_BYTE (start) == '\n')
11421 it.current_x = 0;
11422 if (!NILP (x_limit))
11423 {
11424 it.last_visible_x = max_x;
11425
11426
11427
11428 move_op |= MOVE_TO_X;
11429 to_x = INT_MAX;
11430 }
11431
11432 void *it2data = NULL;
11433 struct it it2;
11434 SAVE_IT (it2, it, it2data);
11435
11436 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11437
11438
11439
11440
11441
11442 if (IT_CHARPOS (it) > end)
11443 {
11444 end--;
11445 RESTORE_IT (&it, &it2, it2data);
11446 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11447
11448
11449
11450 if (IT_CHARPOS (it) == end)
11451 {
11452 x += it.pixel_width;
11453
11454
11455 if (!NILP (ignore_line_at_end))
11456 doff = (max (it.max_ascent, it.ascent)
11457 + max (it.max_descent, it.descent));
11458 else
11459 {
11460 it.max_ascent = max (it.max_ascent, it.ascent);
11461 it.max_descent = max (it.max_descent, it.descent);
11462 }
11463 }
11464 }
11465 else
11466 bidi_unshelve_cache (it2data, true);
11467
11468 if (!NILP (x_limit))
11469 {
11470
11471 if (x > max_x)
11472 x = max_x;
11473 }
11474
11475
11476
11477
11478 if (it.current_y > start_y)
11479 start_x = 0;
11480
11481
11482
11483 if (!NILP (ignore_line_at_end))
11484 y = (it.current_y + doff
11485 - WINDOW_TAB_LINE_HEIGHT (w)
11486 - WINDOW_HEADER_LINE_HEIGHT (w));
11487 else
11488 y = (it.current_y + it.max_ascent + it.max_descent + doff
11489 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11490
11491
11492 if (y > max_y)
11493 y = max_y;
11494
11495 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11496 && window_wants_tab_line (w))
11497
11498 {
11499 Lisp_Object window_tab_line_format
11500 = window_parameter (w, Qtab_line_format);
11501
11502 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11503 NILP (window_tab_line_format)
11504 ? BVAR (current_buffer, tab_line_format)
11505 : window_tab_line_format);
11506 }
11507
11508 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11509 && window_wants_header_line (w))
11510 {
11511 Lisp_Object window_header_line_format
11512 = window_parameter (w, Qheader_line_format);
11513
11514 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11515 NILP (window_header_line_format)
11516 ? BVAR (current_buffer, header_line_format)
11517 : window_header_line_format);
11518 }
11519
11520 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11521 && window_wants_mode_line (w))
11522 {
11523 Lisp_Object window_mode_line_format
11524 = window_parameter (w, Qmode_line_format);
11525
11526 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11527 NILP (window_mode_line_format)
11528 ? BVAR (current_buffer, mode_line_format)
11529 : window_mode_line_format);
11530 }
11531
11532 bidi_unshelve_cache (itdata, false);
11533
11534 return (!vertical_offset
11535 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11536 : list3i (x - start_x, y, start));
11537 }
11538
11539 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11540 doc:
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595 )
11596 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11597 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11598 {
11599 struct window *w = decode_live_window (window);
11600 struct buffer *b = XBUFFER (w->contents);
11601 struct buffer *old_b = NULL;
11602 Lisp_Object value;
11603
11604 if (b != current_buffer)
11605 {
11606 old_b = current_buffer;
11607 set_buffer_internal_1 (b);
11608 }
11609
11610 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11611 ignore_line_at_end);
11612
11613 if (old_b)
11614 set_buffer_internal_1 (old_b);
11615
11616 return value;
11617 }
11618
11619 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11620 doc:
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633 )
11634 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11635 Lisp_Object y_limit)
11636 {
11637 struct window *w = decode_live_window (window);
11638 struct buffer *b = (NILP (buffer_or_name)
11639 ? current_buffer
11640 : XBUFFER (Fget_buffer (buffer_or_name)));
11641 Lisp_Object buffer, value;
11642 specpdl_ref count = SPECPDL_INDEX ();
11643
11644 XSETBUFFER (buffer, b);
11645
11646
11647
11648
11649 record_unwind_protect (unwind_with_echo_area_buffer,
11650 with_echo_area_buffer_unwind_data (w));
11651
11652 set_buffer_internal_1 (b);
11653
11654 if (!EQ (buffer, w->contents))
11655 {
11656 wset_buffer (w, buffer);
11657 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11658 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11659 }
11660
11661 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11662 Qnil);
11663
11664 unbind_to (count, Qnil);
11665
11666 return value;
11667 }
11668
11669
11670 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11671 Sdisplay__line_is_continued_p, 0, 0, 0,
11672 doc: )
11673 (void)
11674 {
11675 struct buffer *oldb = current_buffer;
11676 struct window *w = XWINDOW (selected_window);
11677 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11678
11679 set_buffer_internal_1 (XBUFFER (w->contents));
11680
11681 if (PT < ZV)
11682 {
11683 struct text_pos startpos;
11684 struct it it;
11685 void *itdata;
11686
11687
11688 Lisp_Object opoint = Fpoint_marker ();
11689
11690
11691
11692 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11693 SET_TEXT_POS (startpos, PT, PT_BYTE);
11694 itdata = bidi_shelve_cache ();
11695 start_display (&it, w, startpos);
11696
11697 if (it.line_wrap != TRUNCATE)
11698 {
11699 it.glyph_row = NULL;
11700 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11701 }
11702 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11703 bidi_unshelve_cache (itdata, false);
11704 }
11705 set_buffer_internal_1 (oldb);
11706
11707 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11708 }
11709
11710
11711
11712
11713
11714
11715
11716
11717 static ptrdiff_t
11718 format_nargs (char const *format)
11719 {
11720 ptrdiff_t nargs = 0;
11721 for (char const *p = format; (p = strchr (p, '%')); p++)
11722 if (p[1] == '%')
11723 p++;
11724 else
11725 nargs++;
11726 return nargs;
11727 }
11728
11729
11730
11731
11732 void
11733 add_to_log (const char *format, ...)
11734 {
11735 va_list ap;
11736 va_start (ap, format);
11737 vadd_to_log (format, ap);
11738 va_end (ap);
11739 }
11740
11741 void
11742 vadd_to_log (char const *format, va_list ap)
11743 {
11744 ptrdiff_t form_nargs = format_nargs (format);
11745 ptrdiff_t nargs = 1 + form_nargs;
11746 Lisp_Object args[10];
11747 eassert (nargs <= ARRAYELTS (args));
11748 AUTO_STRING (args0, format);
11749 args[0] = args0;
11750 for (ptrdiff_t i = 1; i <= nargs; i++)
11751 args[i] = va_arg (ap, Lisp_Object);
11752 Lisp_Object msg = Qnil;
11753 msg = Fformat_message (nargs, args);
11754
11755 ptrdiff_t len = SBYTES (msg) + 1;
11756 USE_SAFE_ALLOCA;
11757 char *buffer = SAFE_ALLOCA (len);
11758 memcpy (buffer, SDATA (msg), len);
11759
11760 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11761 SAFE_FREE ();
11762 }
11763
11764
11765
11766
11767 void
11768 message_log_maybe_newline (void)
11769 {
11770 if (message_log_need_newline)
11771 message_dolog ("", 0, true, false);
11772 }
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784 void
11785 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11786 {
11787 const unsigned char *msg = (const unsigned char *) m;
11788
11789 if (!NILP (Vmemory_full))
11790 return;
11791
11792 if (!NILP (Vmessage_log_max))
11793 {
11794 struct buffer *oldbuf;
11795 Lisp_Object oldpoint, oldbegv, oldzv;
11796 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11797 ptrdiff_t point_at_end = 0;
11798 ptrdiff_t zv_at_end = 0;
11799 Lisp_Object old_deactivate_mark;
11800
11801 old_deactivate_mark = Vdeactivate_mark;
11802 oldbuf = current_buffer;
11803
11804
11805
11806 if (! STRINGP (Vmessages_buffer_name))
11807 Vmessages_buffer_name = build_string ("*Messages*");
11808
11809
11810 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11811 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11812 if (newbuffer
11813 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11814 call0 (intern ("messages-buffer-mode"));
11815
11816 bset_undo_list (current_buffer, Qt);
11817 bset_cache_long_scans (current_buffer, Qnil);
11818
11819 oldpoint = message_dolog_marker1;
11820 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11821 oldbegv = message_dolog_marker2;
11822 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11823 oldzv = message_dolog_marker3;
11824 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11825
11826 if (PT == Z)
11827 point_at_end = 1;
11828 if (ZV == Z)
11829 zv_at_end = 1;
11830
11831 BEGV = BEG;
11832 BEGV_BYTE = BEG_BYTE;
11833 ZV = Z;
11834 ZV_BYTE = Z_BYTE;
11835 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11836
11837
11838
11839 if (multibyte
11840 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11841 {
11842
11843
11844 for (ptrdiff_t i = 0; i < nbytes; )
11845 {
11846 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11847 char work = CHAR_TO_BYTE8 (c);
11848 insert_1_both (&work, 1, 1, true, false, false);
11849 i += char_bytes;
11850 }
11851 }
11852 else if (! multibyte
11853 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11854 {
11855
11856
11857 for (ptrdiff_t i = 0; i < nbytes; i++)
11858 {
11859 int c = make_char_multibyte (msg[i]);
11860 unsigned char str[MAX_MULTIBYTE_LENGTH];
11861 int char_bytes = CHAR_STRING (c, str);
11862 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11863 }
11864 }
11865 else if (nbytes)
11866 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11867 true, false, false);
11868
11869 if (nlflag)
11870 {
11871 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11872 intmax_t dups;
11873
11874
11875
11876
11877
11878 specpdl_ref count = SPECPDL_INDEX ();
11879 specbind (Qinhibit_modification_hooks, Qt);
11880
11881 insert_1_both ("\n", 1, 1, true, false, false);
11882
11883 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11884 this_bol = PT;
11885 this_bol_byte = PT_BYTE;
11886
11887
11888
11889 if (this_bol > BEG)
11890 {
11891 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11892 prev_bol = PT;
11893 prev_bol_byte = PT_BYTE;
11894
11895 dups = message_log_check_duplicate (prev_bol_byte,
11896 this_bol_byte);
11897 if (dups)
11898 {
11899 del_range_both (prev_bol, prev_bol_byte,
11900 this_bol, this_bol_byte, false);
11901 if (dups > 1)
11902 {
11903 char dupstr[sizeof " [ times]"
11904 + INT_STRLEN_BOUND (dups)];
11905
11906
11907
11908 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11909 dups);
11910 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11911 insert_1_both (dupstr, duplen, duplen,
11912 true, false, true);
11913 }
11914 }
11915 }
11916
11917
11918
11919
11920
11921 if (FIXNATP (Vmessage_log_max))
11922 {
11923 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11924 -XFIXNAT (Vmessage_log_max) - 1, false);
11925 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11926 }
11927
11928 unbind_to (count, Qnil);
11929 }
11930 BEGV = marker_position (oldbegv);
11931 BEGV_BYTE = marker_byte_position (oldbegv);
11932
11933 if (zv_at_end)
11934 {
11935 ZV = Z;
11936 ZV_BYTE = Z_BYTE;
11937 }
11938 else
11939 {
11940 ZV = marker_position (oldzv);
11941 ZV_BYTE = marker_byte_position (oldzv);
11942 }
11943
11944 if (point_at_end)
11945 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11946 else
11947
11948
11949 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11950 marker_byte_position (oldpoint));
11951
11952 unchain_marker (XMARKER (oldpoint));
11953 unchain_marker (XMARKER (oldbegv));
11954 unchain_marker (XMARKER (oldzv));
11955
11956
11957
11958
11959
11960
11961
11962 windows_or_buffers_changed = old_windows_or_buffers_changed;
11963 bset_redisplay (current_buffer);
11964
11965 set_buffer_internal (oldbuf);
11966
11967 message_log_need_newline = !nlflag;
11968 Vdeactivate_mark = old_deactivate_mark;
11969 }
11970 }
11971
11972
11973
11974
11975
11976
11977
11978
11979 static intmax_t
11980 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
11981 {
11982 ptrdiff_t i;
11983 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
11984 bool seen_dots = false;
11985 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
11986 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
11987
11988 for (i = 0; i < len; i++)
11989 {
11990 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
11991 seen_dots = true;
11992 if (p1[i] != p2[i])
11993 return seen_dots;
11994 }
11995 p1 += len;
11996 if (*p1 == '\n')
11997 return 2;
11998 if (*p1++ == ' ' && *p1++ == '[')
11999 {
12000 char *pend;
12001 intmax_t n = strtoimax ((char *) p1, &pend, 10);
12002 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
12003 return n + 1;
12004 }
12005 return 0;
12006 }
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016 void
12017 message3 (Lisp_Object m)
12018 {
12019 clear_message (true, true);
12020 cancel_echoing ();
12021
12022
12023 message_log_maybe_newline ();
12024 if (STRINGP (m))
12025 {
12026 ptrdiff_t nbytes = SBYTES (m);
12027 bool multibyte = STRING_MULTIBYTE (m);
12028 char *buffer;
12029 USE_SAFE_ALLOCA;
12030 SAFE_ALLOCA_STRING (buffer, m);
12031 message_dolog (buffer, nbytes, true, multibyte);
12032 SAFE_FREE ();
12033 }
12034 if (! inhibit_message)
12035 message3_nolog (m);
12036 }
12037
12038
12039
12040 static void
12041 message_to_stderr (Lisp_Object m)
12042 {
12043 if (noninteractive_need_newline)
12044 {
12045 noninteractive_need_newline = false;
12046 errputc ('\n');
12047 }
12048 if (STRINGP (m))
12049 {
12050 Lisp_Object coding_system = Vlocale_coding_system;
12051 Lisp_Object s;
12052
12053 if (!NILP (Vcoding_system_for_write))
12054 coding_system = Vcoding_system_for_write;
12055 if (!NILP (coding_system))
12056 s = code_convert_string_norecord (m, coding_system, true);
12057 else
12058 s = m;
12059
12060 errwrite (SDATA (s), SBYTES (s));
12061 }
12062 if (STRINGP (m) || !cursor_in_echo_area)
12063 errputc ('\n');
12064 }
12065
12066
12067
12068
12069
12070
12071 void
12072 message3_nolog (Lisp_Object m)
12073 {
12074 struct frame *sf = SELECTED_FRAME ();
12075
12076 if (FRAME_INITIAL_P (sf))
12077 message_to_stderr (m);
12078
12079
12080
12081 else if (INTERACTIVE && sf->glyphs_initialized_p)
12082 {
12083
12084
12085 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12086 Lisp_Object frame = XWINDOW (mini_window)->frame;
12087 struct frame *f = XFRAME (frame);
12088
12089 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12090 Fmake_frame_visible (frame);
12091
12092 if (STRINGP (m) && SCHARS (m) > 0)
12093 {
12094 set_message (m);
12095 if (minibuffer_auto_raise)
12096 Fraise_frame (frame);
12097
12098
12099 echo_message_buffer = Qnil;
12100 }
12101 else
12102 clear_message (true, true);
12103
12104 do_pending_window_change (false);
12105 echo_area_display (true);
12106 do_pending_window_change (false);
12107 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12108 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12109 }
12110 }
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121 void
12122 message1 (const char *m)
12123 {
12124 message3 (m ? build_unibyte_string (m) : Qnil);
12125 }
12126
12127
12128
12129
12130 void
12131 message1_nolog (const char *m)
12132 {
12133 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12134 }
12135
12136
12137
12138
12139 void
12140 message_with_string (const char *m, Lisp_Object string, bool log)
12141 {
12142 CHECK_STRING (string);
12143
12144 bool need_message;
12145 if (noninteractive)
12146 need_message = !!m;
12147 else if (!INTERACTIVE)
12148 need_message = false;
12149 else
12150 {
12151
12152
12153
12154 Lisp_Object mini_window;
12155 struct frame *f, *sf = SELECTED_FRAME ();
12156
12157
12158
12159 mini_window = FRAME_MINIBUF_WINDOW (sf);
12160 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12161
12162
12163
12164
12165 need_message = f->glyphs_initialized_p;
12166 }
12167
12168 if (need_message)
12169 {
12170 AUTO_STRING (fmt, m);
12171 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12172
12173 if (noninteractive)
12174 message_to_stderr (msg);
12175 else
12176 {
12177 if (log)
12178 message3 (msg);
12179 else
12180 message3_nolog (msg);
12181
12182
12183
12184 message_buf_print = false;
12185 }
12186 }
12187 }
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12201 vmessage (const char *m, va_list ap)
12202 {
12203 if (noninteractive)
12204 {
12205 if (m)
12206 {
12207 if (noninteractive_need_newline)
12208 putc ('\n', stderr);
12209 noninteractive_need_newline = false;
12210 vfprintf (stderr, m, ap);
12211 if (!cursor_in_echo_area)
12212 putc ('\n', stderr);
12213 fflush (stderr);
12214 }
12215 }
12216 else if (INTERACTIVE)
12217 {
12218
12219
12220
12221 Lisp_Object mini_window;
12222 struct frame *f, *sf = SELECTED_FRAME ();
12223
12224
12225
12226 mini_window = FRAME_MINIBUF_WINDOW (sf);
12227 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12228
12229
12230
12231
12232 if (f->glyphs_initialized_p)
12233 {
12234 if (m)
12235 {
12236 ptrdiff_t len;
12237 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12238 USE_SAFE_ALLOCA;
12239 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12240
12241 len = doprnt (message_buf, maxsize, m, 0, ap);
12242
12243 message3 (make_string (message_buf, len));
12244 SAFE_FREE ();
12245 }
12246 else
12247 message1 (0);
12248
12249
12250
12251 message_buf_print = false;
12252 }
12253 }
12254 }
12255
12256
12257 void
12258 message (const char *m, ...)
12259 {
12260 va_list ap;
12261 va_start (ap, m);
12262 vmessage (m, ap);
12263 va_end (ap);
12264 }
12265
12266
12267
12268
12269
12270
12271 void
12272 update_echo_area (void)
12273 {
12274 if (!NILP (echo_area_buffer[0]))
12275 {
12276 Lisp_Object string;
12277 string = Fcurrent_message ();
12278 message3 (string);
12279 }
12280 }
12281
12282
12283
12284
12285
12286 static void
12287 ensure_echo_area_buffers (void)
12288 {
12289 for (int i = 0; i < 2; i++)
12290 if (!BUFFERP (echo_buffer[i])
12291 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12292 {
12293 Lisp_Object old_buffer = echo_buffer[i];
12294 static char const name_fmt[] = " *Echo Area %d*";
12295 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12296 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12297 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12298 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12299
12300
12301
12302
12303 for (int j = 0; j < 2; j++)
12304 if (EQ (old_buffer, echo_area_buffer[j]))
12305 echo_area_buffer[j] = echo_buffer[i];
12306 }
12307 }
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326 static bool
12327 with_echo_area_buffer (struct window *w, int which,
12328 bool (*fn) (void *, Lisp_Object),
12329 void *a1, Lisp_Object a2)
12330 {
12331 Lisp_Object buffer;
12332 bool this_one, the_other, clear_buffer_p, rc;
12333 specpdl_ref count = SPECPDL_INDEX ();
12334
12335
12336 ensure_echo_area_buffers ();
12337
12338 clear_buffer_p = false;
12339
12340 if (which == 0)
12341 this_one = false, the_other = true;
12342 else if (which > 0)
12343 this_one = true, the_other = false;
12344 else
12345 {
12346 this_one = false, the_other = true;
12347 clear_buffer_p = true;
12348
12349
12350
12351 if (!NILP (echo_area_buffer[this_one])
12352 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12353 echo_area_buffer[this_one] = Qnil;
12354 }
12355
12356
12357
12358 if (NILP (echo_area_buffer[this_one]))
12359 {
12360 echo_area_buffer[this_one]
12361 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12362 ? echo_buffer[the_other]
12363 : echo_buffer[this_one]);
12364 clear_buffer_p = true;
12365 }
12366
12367 buffer = echo_area_buffer[this_one];
12368
12369
12370
12371 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12372 cancel_echoing ();
12373
12374 record_unwind_protect (unwind_with_echo_area_buffer,
12375 with_echo_area_buffer_unwind_data (w));
12376
12377
12378
12379
12380
12381
12382
12383
12384 set_buffer_internal_1 (XBUFFER (buffer));
12385 if (w)
12386 {
12387 wset_buffer (w, buffer);
12388 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12389 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12390 }
12391
12392 bset_undo_list (current_buffer, Qt);
12393 bset_read_only (current_buffer, Qnil);
12394 specbind (Qinhibit_read_only, Qt);
12395 specbind (Qinhibit_modification_hooks, Qt);
12396
12397 if (clear_buffer_p && Z > BEG)
12398 del_range (BEG, Z);
12399
12400 eassert (BEGV >= BEG);
12401 eassert (ZV <= Z && ZV >= BEGV);
12402
12403 rc = fn (a1, a2);
12404
12405 eassert (BEGV >= BEG);
12406 eassert (ZV <= Z && ZV >= BEGV);
12407
12408 unbind_to (count, Qnil);
12409 return rc;
12410 }
12411
12412
12413
12414
12415
12416 static Lisp_Object
12417 with_echo_area_buffer_unwind_data (struct window *w)
12418 {
12419 int i = 0;
12420 Lisp_Object vector, tmp;
12421
12422
12423
12424 vector = Vwith_echo_area_save_vector;
12425 Vwith_echo_area_save_vector = Qnil;
12426
12427 if (NILP (vector))
12428 vector = make_nil_vector (11);
12429
12430 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12431 ASET (vector, i, Vdeactivate_mark); ++i;
12432 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12433
12434 if (w)
12435 {
12436 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12437 ASET (vector, i, w->contents); ++i;
12438 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12439 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12440 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12441 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12442 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12443 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12444 }
12445 else
12446 {
12447 int end = i + 8;
12448 for (; i < end; ++i)
12449 ASET (vector, i, Qnil);
12450 }
12451
12452 eassert (i == ASIZE (vector));
12453 return vector;
12454 }
12455
12456
12457
12458
12459
12460 static void
12461 unwind_with_echo_area_buffer (Lisp_Object vector)
12462 {
12463 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12464 Vdeactivate_mark = AREF (vector, 1);
12465 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12466
12467 if (WINDOWP (AREF (vector, 3)))
12468 {
12469 struct window *w;
12470 Lisp_Object buffer;
12471
12472 w = XWINDOW (AREF (vector, 3));
12473 buffer = AREF (vector, 4);
12474
12475 wset_buffer (w, buffer);
12476 set_marker_restricted_both (w->pointm, buffer,
12477 XFIXNAT (AREF (vector, 5)),
12478 XFIXNAT (AREF (vector, 6)));
12479 set_marker_restricted_both (w->old_pointm, buffer,
12480 XFIXNAT (AREF (vector, 7)),
12481 XFIXNAT (AREF (vector, 8)));
12482 set_marker_restricted_both (w->start, buffer,
12483 XFIXNAT (AREF (vector, 9)),
12484 XFIXNAT (AREF (vector, 10)));
12485 }
12486
12487 Vwith_echo_area_save_vector = vector;
12488 }
12489
12490
12491
12492
12493
12494 void
12495 setup_echo_area_for_printing (bool multibyte_p)
12496 {
12497
12498 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12499 Fkill_emacs (Qnil, Qnil);
12500
12501 ensure_echo_area_buffers ();
12502
12503 if (!message_buf_print)
12504 {
12505
12506
12507 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12508 echo_area_buffer[0] = echo_buffer[1];
12509 else
12510 echo_area_buffer[0] = echo_buffer[0];
12511
12512
12513 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12514 bset_truncate_lines (current_buffer, Qnil);
12515
12516 if (Z > BEG)
12517 {
12518 specpdl_ref count = SPECPDL_INDEX ();
12519 specbind (Qinhibit_read_only, Qt);
12520
12521 del_range (BEG, Z);
12522 unbind_to (count, Qnil);
12523 }
12524 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12525
12526
12527
12528
12529
12530
12531
12532 if (unibyte_display_via_language_environment
12533 && !multibyte_p
12534 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12535 Fset_buffer_multibyte (Qnil);
12536 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12537 Fset_buffer_multibyte (Qt);
12538
12539
12540 if (minibuffer_auto_raise)
12541 {
12542 struct frame *sf = SELECTED_FRAME ();
12543 Lisp_Object mini_window;
12544 mini_window = FRAME_MINIBUF_WINDOW (sf);
12545 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12546 }
12547
12548 message_log_maybe_newline ();
12549 message_buf_print = true;
12550 }
12551 else
12552 {
12553 if (NILP (echo_area_buffer[0]))
12554 {
12555 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12556 echo_area_buffer[0] = echo_buffer[1];
12557 else
12558 echo_area_buffer[0] = echo_buffer[0];
12559 }
12560
12561 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12562 {
12563
12564 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12565 bset_truncate_lines (current_buffer, Qnil);
12566 }
12567 }
12568 }
12569
12570
12571
12572
12573
12574
12575
12576 static bool
12577 display_echo_area (struct window *w)
12578 {
12579 bool no_message_p, window_height_changed_p;
12580
12581
12582
12583
12584
12585
12586 specpdl_ref count = inhibit_garbage_collection ();
12587
12588
12589
12590
12591
12592 bool i = display_last_displayed_message_p;
12593
12594
12595
12596 no_message_p = NILP (echo_area_buffer[i]);
12597
12598 window_height_changed_p
12599 = with_echo_area_buffer (w, display_last_displayed_message_p,
12600 display_echo_area_1, w, Qnil);
12601
12602 if (no_message_p)
12603 echo_area_buffer[i] = Qnil;
12604
12605 unbind_to (count, Qnil);
12606 return window_height_changed_p;
12607 }
12608
12609
12610
12611
12612
12613
12614
12615
12616 static bool
12617 display_echo_area_1 (void *a1, Lisp_Object a2)
12618 {
12619 struct window *w = a1;
12620 Lisp_Object window;
12621 struct text_pos start;
12622
12623
12624
12625
12626 forget_escape_and_glyphless_faces ();
12627
12628
12629
12630
12631 bool window_height_changed_p = resize_mini_window (w, false);
12632
12633
12634 SET_TEXT_POS_FROM_MARKER (start, w->start);
12635
12636
12637 clear_glyph_matrix (w->desired_matrix);
12638 XSETWINDOW (window, w);
12639 void *itdata = bidi_shelve_cache ();
12640 try_window (window, start, 0);
12641 bidi_unshelve_cache (itdata, false);
12642
12643 return window_height_changed_p;
12644 }
12645
12646
12647
12648
12649
12650
12651 void
12652 resize_echo_area_exactly (void)
12653 {
12654 if (BUFFERP (echo_area_buffer[0])
12655 && WINDOWP (echo_area_window))
12656 {
12657 struct window *w = XWINDOW (echo_area_window);
12658 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12659 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12660 w, resize_exactly);
12661 if (resized_p)
12662 {
12663 windows_or_buffers_changed = 42;
12664 update_mode_lines = 30;
12665 redisplay_internal ();
12666 }
12667 }
12668 }
12669
12670
12671
12672
12673
12674
12675
12676
12677 static bool
12678 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12679 {
12680 return resize_mini_window (a1, !NILP (exactly));
12681 }
12682
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692
12693
12694
12695 bool
12696 resize_mini_window (struct window *w, bool exact_p)
12697 {
12698 struct frame *f = XFRAME (w->frame);
12699 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12700
12701 eassert (MINI_WINDOW_P (w));
12702
12703
12704
12705
12706
12707
12708
12709 if (!NILP (Vinhibit_redisplay))
12710 return false;
12711
12712
12713 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12714 set_marker_both (w->start, w->contents,
12715 BUF_BEGV (XBUFFER (w->contents)),
12716 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12717
12718
12719 if ((NILP (Vresize_mini_windows)
12720 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12721 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12722 return false;
12723
12724 if (FRAME_MINIBUF_ONLY_P (f))
12725 {
12726 if (!NILP (resize_mini_frames))
12727 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12728 }
12729 else
12730 {
12731 struct it it;
12732 int unit = FRAME_LINE_HEIGHT (f);
12733 int height, max_height;
12734 struct text_pos start;
12735 struct buffer *old_current_buffer = NULL;
12736 int windows_height = FRAME_INNER_HEIGHT (f);
12737
12738 if (current_buffer != XBUFFER (w->contents))
12739 {
12740 old_current_buffer = current_buffer;
12741 set_buffer_internal (XBUFFER (w->contents));
12742 }
12743
12744 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12745
12746
12747 if (FLOATP (Vmax_mini_window_height))
12748 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12749 else if (FIXNUMP (Vmax_mini_window_height))
12750 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12751 else
12752 max_height = windows_height / 4;
12753
12754
12755 max_height = clip_to_bounds (unit, max_height, windows_height);
12756
12757
12758 last_height = 0;
12759 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12760
12761
12762 if (it.max_ascent == 0 && it.max_descent == 0)
12763 {
12764 height = it.current_y;
12765
12766
12767
12768
12769
12770 if (!(it.line_wrap == TRUNCATE
12771 && it.current_x <= it.first_visible_x
12772 && ZV_BYTE > 1
12773 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12774 height += last_height;
12775 }
12776 else
12777 height = it.current_y + it.max_ascent + it.max_descent;
12778 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12779
12780
12781 if (height > max_height)
12782 {
12783 height = (max_height / unit) * unit;
12784 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12785 {
12786 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12787 move_it_vertically_backward (&it, height - unit);
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797 move_it_by_lines (&it, 0);
12798 start = it.current.pos;
12799
12800
12801 w->start_at_line_beg = false;
12802 SET_MARKER_FROM_TEXT_POS (w->start, start);
12803 }
12804 }
12805 else
12806 {
12807 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12808 SET_MARKER_FROM_TEXT_POS (w->start, start);
12809 }
12810
12811 if (EQ (Vresize_mini_windows, Qgrow_only))
12812 {
12813
12814
12815 if (height > old_height)
12816 grow_mini_window (w, height - old_height);
12817 else if (height < old_height && (exact_p || BEGV == ZV))
12818 shrink_mini_window (w);
12819 }
12820 else if (height != old_height)
12821
12822 grow_mini_window (w, height - old_height);
12823
12824 if (old_current_buffer)
12825 set_buffer_internal (old_current_buffer);
12826 }
12827
12828 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12829 }
12830
12831
12832
12833
12834
12835 Lisp_Object
12836 current_message (void)
12837 {
12838 Lisp_Object msg;
12839
12840 if (!BUFFERP (echo_area_buffer[0]))
12841 msg = Qnil;
12842 else
12843 {
12844 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12845 if (NILP (msg))
12846 echo_area_buffer[0] = Qnil;
12847 }
12848
12849 return msg;
12850 }
12851
12852
12853 static bool
12854 current_message_1 (void *a1, Lisp_Object a2)
12855 {
12856 Lisp_Object *msg = a1;
12857
12858 if (Z > BEG)
12859 *msg = make_buffer_string (BEG, Z, true);
12860 else
12861 *msg = Qnil;
12862 return false;
12863 }
12864
12865
12866
12867
12868
12869
12870
12871 bool
12872 push_message (void)
12873 {
12874 Lisp_Object msg = current_message ();
12875 Vmessage_stack = Fcons (msg, Vmessage_stack);
12876 return STRINGP (msg);
12877 }
12878
12879
12880
12881
12882 void
12883 restore_message (void)
12884 {
12885 eassert (CONSP (Vmessage_stack));
12886 message3_nolog (XCAR (Vmessage_stack));
12887 }
12888
12889
12890
12891
12892 void
12893 pop_message_unwind (void)
12894 {
12895
12896 eassert (CONSP (Vmessage_stack));
12897 Vmessage_stack = XCDR (Vmessage_stack);
12898 }
12899
12900
12901
12902
12903
12904
12905 void
12906 check_message_stack (void)
12907 {
12908 if (!NILP (Vmessage_stack))
12909 emacs_abort ();
12910 }
12911
12912 void
12913 clear_message_stack (void)
12914 {
12915 Vmessage_stack = Qnil;
12916 }
12917
12918
12919
12920
12921 void
12922 truncate_echo_area (ptrdiff_t nchars)
12923 {
12924 if (nchars == 0)
12925 echo_area_buffer[0] = Qnil;
12926 else if (!noninteractive
12927 && INTERACTIVE
12928 && !NILP (echo_area_buffer[0]))
12929 {
12930 struct frame *sf = SELECTED_FRAME ();
12931
12932
12933
12934 if (sf->glyphs_initialized_p)
12935 with_echo_area_buffer (0, 0, truncate_message_1,
12936 (void *) (intptr_t) nchars, Qnil);
12937 }
12938 }
12939
12940
12941
12942
12943
12944 static bool
12945 truncate_message_1 (void *a1, Lisp_Object a2)
12946 {
12947 intptr_t nchars = (intptr_t) a1;
12948 if (BEG + nchars < Z)
12949 del_range (BEG + nchars, Z);
12950 if (Z == BEG)
12951 echo_area_buffer[0] = Qnil;
12952 return false;
12953 }
12954
12955 extern intptr_t garbage_collection_inhibited;
12956
12957
12958
12959 static void
12960 set_message (Lisp_Object string)
12961 {
12962 Lisp_Object message = Qnil;
12963
12964 eassert (STRINGP (string));
12965
12966 if (FUNCTIONP (Vset_message_function)
12967
12968
12969
12970 && !garbage_collection_inhibited)
12971 {
12972 specpdl_ref count = SPECPDL_INDEX ();
12973 specbind (Qinhibit_quit, Qt);
12974 message = safe_call1 (Vset_message_function, string);
12975 unbind_to (count, Qnil);
12976
12977 if (STRINGP (message))
12978 {
12979 string = message;
12980 message = Qnil;
12981 }
12982 }
12983
12984 if (NILP (message))
12985 {
12986 message_enable_multibyte = STRING_MULTIBYTE (string);
12987
12988 with_echo_area_buffer (0, -1, set_message_1, 0, string);
12989 message_buf_print = false;
12990 help_echo_showing_p = false;
12991 }
12992
12993 if (STRINGP (Vdebug_on_message)
12994 && STRINGP (string)
12995 && fast_string_match (Vdebug_on_message, string) >= 0)
12996 call_debugger (list2 (Qerror, string));
12997 }
12998
12999
13000
13001
13002
13003
13004 static bool
13005 set_message_1 (void *a1, Lisp_Object string)
13006 {
13007 eassert (STRINGP (string));
13008
13009
13010
13011
13012
13013
13014 if (!message_enable_multibyte
13015 && unibyte_display_via_language_environment
13016 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13017 Fset_buffer_multibyte (Qnil);
13018 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13019 Fset_buffer_multibyte (Qt);
13020
13021 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13022 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13023 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13024
13025
13026 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13027
13028
13029
13030
13031 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13032
13033 return false;
13034 }
13035
13036
13037
13038
13039
13040 void
13041 clear_message (bool current_p, bool last_displayed_p)
13042 {
13043 Lisp_Object preserve = Qnil;
13044
13045 if (current_p)
13046 {
13047 if (FUNCTIONP (Vclear_message_function)
13048
13049 && !garbage_collection_inhibited)
13050 {
13051 specpdl_ref count = SPECPDL_INDEX ();
13052 specbind (Qinhibit_quit, Qt);
13053 preserve = safe_call (1, Vclear_message_function);
13054 unbind_to (count, Qnil);
13055 }
13056
13057 if (!EQ (preserve, Qdont_clear_message))
13058 {
13059 echo_area_buffer[0] = Qnil;
13060 message_cleared_p = true;
13061 }
13062 }
13063
13064 if (last_displayed_p)
13065 echo_area_buffer[1] = Qnil;
13066
13067 message_buf_print = false;
13068 }
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079 static void
13080 clear_garbaged_frames (void)
13081 {
13082 if (frame_garbaged)
13083 {
13084 Lisp_Object tail, frame;
13085 struct frame *sf = SELECTED_FRAME ();
13086
13087 FOR_EACH_FRAME (tail, frame)
13088 {
13089 struct frame *f = XFRAME (frame);
13090
13091 if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
13092 {
13093 if (f->resized_p
13094
13095
13096
13097
13098
13099 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13100 redraw_frame (f);
13101 else
13102 clear_current_matrices (f);
13103
13104 #ifdef HAVE_WINDOW_SYSTEM
13105 if (FRAME_WINDOW_P (f)
13106 && FRAME_RIF (f)->clear_under_internal_border)
13107 FRAME_RIF (f)->clear_under_internal_border (f);
13108 #endif
13109 fset_redisplay (f);
13110 f->garbaged = false;
13111 f->resized_p = false;
13112 }
13113 }
13114
13115 frame_garbaged = false;
13116 }
13117 }
13118
13119
13120
13121
13122
13123 static void
13124 echo_area_display (bool update_frame_p)
13125 {
13126 Lisp_Object mini_window;
13127 struct window *w;
13128 struct frame *f;
13129 bool window_height_changed_p = false;
13130 struct frame *sf = SELECTED_FRAME ();
13131
13132 mini_window = FRAME_MINIBUF_WINDOW (sf);
13133 if (NILP (mini_window))
13134 return;
13135
13136 w = XWINDOW (mini_window);
13137 f = XFRAME (WINDOW_FRAME (w));
13138
13139
13140 if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
13141 return;
13142
13143 #ifdef HAVE_WINDOW_SYSTEM
13144
13145
13146
13147 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13148 return;
13149 #endif
13150
13151
13152 clear_garbaged_frames ();
13153
13154 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13155 {
13156 echo_area_window = mini_window;
13157 window_height_changed_p = display_echo_area (w);
13158 w->must_be_updated_p = true;
13159
13160
13161
13162
13163
13164 if (update_frame_p && !redisplaying_p)
13165 {
13166 int n = 0;
13167
13168
13169
13170
13171
13172
13173 if (!display_completed)
13174 {
13175 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13176
13177 #ifdef HAVE_WINDOW_SYSTEM
13178 if (FRAME_WINDOW_P (f)
13179 && FRAME_RIF (f)->clear_under_internal_border)
13180 FRAME_RIF (f)->clear_under_internal_border (f);
13181 #endif
13182 }
13183
13184 if (window_height_changed_p
13185
13186
13187 && !NILP (Vrun_hooks))
13188 {
13189
13190
13191
13192 specpdl_ref count = SPECPDL_INDEX ();
13193 specbind (Qredisplay_dont_pause, Qt);
13194 fset_redisplay (f);
13195 redisplay_internal ();
13196 unbind_to (count, Qnil);
13197 }
13198 else if (FRAME_WINDOW_P (f) && n == 0)
13199 {
13200
13201
13202
13203 update_single_window (w);
13204 flush_frame (f);
13205 }
13206 else
13207 update_frame (f, true, true);
13208
13209
13210
13211
13212 if (cursor_in_echo_area)
13213 wset_redisplay (XWINDOW (mini_window));
13214 }
13215 }
13216 else if (!EQ (mini_window, selected_window))
13217 wset_redisplay (XWINDOW (mini_window));
13218
13219
13220 echo_area_buffer[1] = echo_area_buffer[0];
13221
13222 echo_message_buffer = Qnil;
13223
13224
13225
13226
13227 if (EQ (mini_window, selected_window))
13228 CHARPOS (this_line_start_pos) = 0;
13229
13230 if (window_height_changed_p)
13231 {
13232 fset_redisplay (f);
13233
13234
13235
13236
13237
13238 clear_garbaged_frames ();
13239 }
13240 }
13241
13242
13243
13244 static bool
13245 window_buffer_changed (struct window *w)
13246 {
13247 struct buffer *b = XBUFFER (w->contents);
13248
13249 eassert (BUFFER_LIVE_P (b));
13250
13251 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13252 }
13253
13254
13255
13256 static bool
13257 mode_line_update_needed (struct window *w)
13258 {
13259 return (w->column_number_displayed != -1
13260 && !(PT == w->last_point && !window_outdated (w))
13261 && (w->column_number_displayed != current_column ()));
13262 }
13263
13264
13265
13266
13267 static bool
13268 window_frozen_p (struct window *w)
13269 {
13270 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13271 {
13272 Lisp_Object window;
13273
13274 XSETWINDOW (window, w);
13275 if (MINI_WINDOW_P (w))
13276 return false;
13277 else if (EQ (window, selected_window))
13278 return false;
13279 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13280 && EQ (window, Vminibuf_scroll_window))
13281
13282 return false;
13283 else
13284 return true;
13285 }
13286 return false;
13287 }
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297 static char *mode_line_noprop_buf;
13298
13299
13300
13301 static char *mode_line_noprop_buf_end;
13302 static char *mode_line_noprop_ptr;
13303
13304 #define MODE_LINE_NOPROP_LEN(start) \
13305 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13306
13307 static enum {
13308 MODE_LINE_DISPLAY = 0,
13309 MODE_LINE_TITLE,
13310 MODE_LINE_NOPROP,
13311 MODE_LINE_STRING
13312 } mode_line_target;
13313
13314
13315
13316 static Lisp_Object mode_line_proptrans_alist;
13317
13318
13319 static Lisp_Object mode_line_string_list;
13320
13321
13322 static Lisp_Object mode_line_string_face;
13323 static Lisp_Object mode_line_string_face_prop;
13324
13325
13326
13327
13328 static Lisp_Object Vmode_line_unwind_vector;
13329
13330 static Lisp_Object
13331 format_mode_line_unwind_data (struct frame *target_frame,
13332 struct buffer *obuf,
13333 Lisp_Object owin,
13334 bool save_proptrans)
13335 {
13336 Lisp_Object vector, tmp;
13337
13338
13339
13340 vector = Vmode_line_unwind_vector;
13341 Vmode_line_unwind_vector = Qnil;
13342
13343 if (NILP (vector))
13344 vector = make_nil_vector (12);
13345
13346 ASET (vector, 0, make_fixnum (mode_line_target));
13347 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13348 ASET (vector, 2, mode_line_string_list);
13349 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13350 ASET (vector, 4, mode_line_string_face);
13351 ASET (vector, 5, mode_line_string_face_prop);
13352
13353 if (obuf)
13354 XSETBUFFER (tmp, obuf);
13355 else
13356 tmp = Qnil;
13357 ASET (vector, 6, tmp);
13358 ASET (vector, 7, owin);
13359 if (target_frame)
13360 {
13361 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13362 struct buffer *b = XBUFFER (buffer);
13363 struct buffer *cb = current_buffer;
13364
13365
13366
13367
13368 ASET (vector, 8, target_frame->selected_window);
13369 if (FRAME_TERMCAP_P (target_frame))
13370 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13371
13372
13373
13374
13375 ASET (vector, 10, buffer);
13376 current_buffer = b;
13377 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13378 current_buffer = cb;
13379 }
13380
13381 return vector;
13382 }
13383
13384 static void
13385 unwind_format_mode_line (Lisp_Object vector)
13386 {
13387 Lisp_Object old_window = AREF (vector, 7);
13388 Lisp_Object target_frame_window = AREF (vector, 8);
13389 Lisp_Object old_top_frame = AREF (vector, 9);
13390
13391 mode_line_target = XFIXNUM (AREF (vector, 0));
13392 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13393 mode_line_string_list = AREF (vector, 2);
13394 if (! EQ (AREF (vector, 3), Qt))
13395 mode_line_proptrans_alist = AREF (vector, 3);
13396 mode_line_string_face = AREF (vector, 4);
13397 mode_line_string_face_prop = AREF (vector, 5);
13398
13399
13400 if (WINDOW_LIVE_P (old_window))
13401 {
13402
13403
13404
13405 if (WINDOW_LIVE_P (target_frame_window))
13406 {
13407 Lisp_Object frame
13408 = WINDOW_FRAME (XWINDOW (target_frame_window));
13409
13410 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13411 Fselect_window (target_frame_window, Qt);
13412
13413 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13414
13415
13416 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13417 Fselect_frame (old_top_frame, Qt);
13418 }
13419
13420 Fselect_window (old_window, Qt);
13421
13422
13423
13424
13425 if (WINDOW_LIVE_P (target_frame_window))
13426 {
13427 Lisp_Object buffer = AREF (vector, 10);
13428
13429 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13430 {
13431 struct buffer *cb = current_buffer;
13432
13433 current_buffer = XBUFFER (buffer);
13434 set_point_from_marker (AREF (vector, 11));
13435 ASET (vector, 11, Qnil);
13436 current_buffer = cb;
13437 }
13438 }
13439 }
13440
13441 if (!NILP (AREF (vector, 6)))
13442 {
13443 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13444 ASET (vector, 6, Qnil);
13445 }
13446
13447 Vmode_line_unwind_vector = vector;
13448 }
13449
13450
13451
13452
13453
13454 static void
13455 store_mode_line_noprop_char (char c)
13456 {
13457
13458
13459 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13460 {
13461 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13462 ptrdiff_t size = len;
13463 mode_line_noprop_buf =
13464 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13465 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13466 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13467 }
13468
13469 *mode_line_noprop_ptr++ = c;
13470 }
13471
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481 static int
13482 store_mode_line_noprop (const char *string, int field_width, int precision)
13483 {
13484 const unsigned char *str = (const unsigned char *) string;
13485 int n = 0;
13486 ptrdiff_t dummy, nbytes;
13487
13488
13489 nbytes = strlen (string);
13490 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13491 while (nbytes--)
13492 store_mode_line_noprop_char (*str++);
13493
13494
13495 while (field_width > 0
13496 && n < field_width)
13497 {
13498 store_mode_line_noprop_char (' ');
13499 ++n;
13500 }
13501
13502 return n;
13503 }
13504
13505
13506
13507
13508
13509 #ifdef HAVE_WINDOW_SYSTEM
13510
13511
13512
13513
13514
13515 void
13516 gui_consider_frame_title (Lisp_Object frame)
13517 {
13518 struct frame *f = XFRAME (frame);
13519 Lisp_Object format_data;
13520
13521 if ((FRAME_WINDOW_P (f)
13522 || FRAME_MINIBUF_ONLY_P (f)
13523 || f->explicit_name)
13524 && !FRAME_TOOLTIP_P (f))
13525 {
13526
13527 Lisp_Object tail, other_frame, fmt;
13528 ptrdiff_t title_start;
13529 char *title;
13530 ptrdiff_t len;
13531 struct it it;
13532 specpdl_ref count = SPECPDL_INDEX ();
13533
13534 FOR_EACH_FRAME (tail, other_frame)
13535 {
13536 struct frame *tf = XFRAME (other_frame);
13537
13538 if (tf != f
13539 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13540 && !FRAME_MINIBUF_ONLY_P (tf)
13541 && !FRAME_PARENT_FRAME (tf)
13542 && !FRAME_TOOLTIP_P (tf)
13543 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13544 break;
13545 }
13546
13547
13548 multiple_frames = CONSP (tail);
13549
13550
13551
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561 specbind (Qinhibit_redisplay, Qt);
13562
13563
13564
13565
13566
13567
13568
13569
13570 format_data = format_mode_line_unwind_data (f, current_buffer,
13571 selected_window,
13572 false);
13573 record_unwind_protect (unwind_format_mode_line, format_data);
13574
13575 Fselect_window (f->selected_window, Qt);
13576 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13577 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13578 ? Vicon_title_format : Vframe_title_format);
13579
13580 mode_line_target = MODE_LINE_TITLE;
13581 title_start = MODE_LINE_NOPROP_LEN (0);
13582 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13583 NULL, DEFAULT_FACE_ID);
13584 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13585 len = MODE_LINE_NOPROP_LEN (title_start);
13586 title = mode_line_noprop_buf + title_start;
13587
13588
13589 ptrdiff_t nchars = 0;
13590 len = str_as_multibyte ((unsigned char *) title,
13591 mode_line_noprop_buf_end - title,
13592 len, &nchars);
13593 unbind_to (count, Qnil);
13594
13595
13596
13597
13598
13599
13600 if ((! STRINGP (f->name)
13601 || SBYTES (f->name) != len
13602 || memcmp (title, SDATA (f->name), len) != 0)
13603 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13604 {
13605 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13606 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13607 }
13608 }
13609 }
13610
13611 #endif
13612
13613
13614
13615
13616
13617
13618
13619 #define REDISPLAY_SOME_P() \
13620 ((windows_or_buffers_changed == 0 \
13621 || windows_or_buffers_changed == REDISPLAY_SOME) \
13622 && (update_mode_lines == 0 \
13623 || update_mode_lines == REDISPLAY_SOME))
13624
13625 static bool
13626 needs_no_redisplay (struct window *w)
13627 {
13628 struct buffer *buffer = XBUFFER (w->contents);
13629 struct frame *f = XFRAME (w->frame);
13630 return (REDISPLAY_SOME_P ()
13631 && !w->redisplay
13632 && !w->update_mode_line
13633 && !f->face_change
13634 && !f->redisplay
13635 && !buffer->text->redisplay
13636 && window_point (w) == w->last_point);
13637 }
13638
13639
13640
13641
13642 static void
13643 prepare_menu_bars (void)
13644 {
13645 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13646 bool some_windows = REDISPLAY_SOME_P ();
13647
13648 if (FUNCTIONP (Vpre_redisplay_function))
13649 {
13650 Lisp_Object windows = all_windows ? Qt : Qnil;
13651 if (all_windows && some_windows)
13652 {
13653 Lisp_Object ws = window_list ();
13654 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13655 {
13656 Lisp_Object this = XCAR (ws);
13657 struct window *w = XWINDOW (this);
13658
13659
13660 if (!needs_no_redisplay (w))
13661 windows = Fcons (this, windows);
13662 }
13663 }
13664 safe__call1 (true, Vpre_redisplay_function, windows);
13665 }
13666
13667
13668
13669
13670 #ifdef HAVE_WINDOW_SYSTEM
13671 if (all_windows)
13672 {
13673 Lisp_Object tail, frame;
13674
13675 FOR_EACH_FRAME (tail, frame)
13676 {
13677 struct frame *f = XFRAME (frame);
13678 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13679 if (some_windows
13680 && !f->redisplay
13681 && !w->redisplay
13682 && !XBUFFER (w->contents)->text->redisplay)
13683 continue;
13684
13685 if (!FRAME_TOOLTIP_P (f)
13686 && (FRAME_ICONIFIED_P (f)
13687 || FRAME_VISIBLE_P (f) == 1
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697 || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
13698 gui_consider_frame_title (frame);
13699 }
13700 }
13701 #endif
13702
13703
13704
13705
13706 if (all_windows)
13707 {
13708 Lisp_Object tail, frame;
13709 specpdl_ref count = SPECPDL_INDEX ();
13710
13711
13712 bool menu_bar_hooks_run = false;
13713
13714 record_unwind_save_match_data ();
13715
13716 FOR_EACH_FRAME (tail, frame)
13717 {
13718 struct frame *f = XFRAME (frame);
13719 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13720
13721
13722 if (FRAME_TOOLTIP_P (f))
13723 continue;
13724
13725 if (some_windows
13726 && !f->redisplay
13727 && !w->redisplay
13728 && !XBUFFER (w->contents)->text->redisplay)
13729 continue;
13730
13731 if (!FRAME_PARENT_FRAME (f))
13732 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13733
13734 update_tab_bar (f, false);
13735 #ifdef HAVE_WINDOW_SYSTEM
13736 update_tool_bar (f, false);
13737 #endif
13738 }
13739
13740 unbind_to (count, Qnil);
13741 }
13742 else
13743 {
13744 struct frame *sf = SELECTED_FRAME ();
13745
13746 if (!FRAME_PARENT_FRAME (sf))
13747 update_menu_bar (sf, true, false);
13748
13749 update_tab_bar (sf, true);
13750 #ifdef HAVE_WINDOW_SYSTEM
13751 update_tool_bar (sf, true);
13752 #endif
13753 }
13754 }
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768 static bool
13769 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13770 {
13771 Lisp_Object window;
13772 struct window *w;
13773
13774
13775
13776
13777 if (inhibit_menubar_update)
13778 return hooks_run;
13779
13780 window = FRAME_SELECTED_WINDOW (f);
13781 w = XWINDOW (window);
13782
13783 if (FRAME_WINDOW_P (f)
13784 ?
13785 #ifdef HAVE_EXT_MENU_BAR
13786 FRAME_EXTERNAL_MENU_BAR (f)
13787 #else
13788 FRAME_MENU_BAR_LINES (f) > 0
13789 #endif
13790 : FRAME_MENU_BAR_LINES (f) > 0)
13791 {
13792
13793
13794
13795
13796
13797
13798
13799 if (windows_or_buffers_changed
13800
13801
13802 || update_mode_lines
13803 || window_buffer_changed (w))
13804 {
13805 struct buffer *prev = current_buffer;
13806 specpdl_ref count = SPECPDL_INDEX ();
13807
13808 specbind (Qinhibit_menubar_update, Qt);
13809
13810 set_buffer_internal_1 (XBUFFER (w->contents));
13811 if (save_match_data)
13812 record_unwind_save_match_data ();
13813 if (NILP (Voverriding_local_map_menu_flag))
13814 {
13815 specbind (Qoverriding_terminal_local_map, Qnil);
13816 specbind (Qoverriding_local_map, Qnil);
13817 }
13818
13819 if (!hooks_run)
13820 {
13821
13822 safe_run_hooks (Qactivate_menubar_hook);
13823
13824
13825
13826 safe_run_hooks (Qmenu_bar_update_hook);
13827
13828 hooks_run = true;
13829 }
13830
13831 XSETFRAME (Vmenu_updating_frame, f);
13832 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13833
13834
13835 #ifdef HAVE_EXT_MENU_BAR
13836 if (FRAME_WINDOW_P (f))
13837 {
13838 #if defined (HAVE_NS)
13839
13840
13841 if (f == SELECTED_FRAME ())
13842 #endif
13843 set_frame_menubar (f, false);
13844 }
13845 else
13846
13847
13848 w->update_mode_line = true;
13849 #else
13850
13851
13852 w->update_mode_line = true;
13853 #endif
13854
13855 unbind_to (count, Qnil);
13856 set_buffer_internal_1 (prev);
13857 }
13858 }
13859
13860 return hooks_run;
13861 }
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874 static void
13875 restore_selected_window (Lisp_Object window)
13876 {
13877 if (WINDOW_LIVE_P (window))
13878
13879
13880 {
13881 selected_window = window;
13882 selected_frame = XWINDOW (window)->frame;
13883 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13884 }
13885 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13886
13887
13888 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13889 else
13890
13891
13892
13893 {
13894 Lisp_Object tail;
13895 Lisp_Object frame UNINIT;
13896
13897 FOR_EACH_FRAME (tail, frame)
13898 {
13899 struct frame *f = XFRAME (frame);
13900
13901 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13902 {
13903 selected_frame = frame;
13904 selected_window = FRAME_SELECTED_WINDOW (f);
13905
13906 return;
13907 }
13908 }
13909
13910
13911 emacs_abort ();
13912 }
13913 }
13914
13915
13916 static void
13917 restore_frame_selected_window (Lisp_Object window)
13918 {
13919 if (WINDOW_LIVE_P (window))
13920
13921
13922
13923 {
13924 Lisp_Object frame = XWINDOW (window)->frame;
13925
13926 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13927 if (EQ (frame, selected_frame))
13928 selected_window = window;
13929 }
13930 }
13931
13932
13933
13934
13935
13936
13937 static void
13938 update_tab_bar (struct frame *f, bool save_match_data)
13939 {
13940 bool do_update = false;
13941
13942 #ifdef HAVE_WINDOW_SYSTEM
13943 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13944 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13945 do_update = true;
13946 }
13947 else
13948 #endif
13949 if (FRAME_TAB_BAR_LINES (f) > 0)
13950 do_update = true;
13951
13952 if (do_update)
13953 {
13954 Lisp_Object window;
13955 struct window *w;
13956
13957 window = FRAME_SELECTED_WINDOW (f);
13958 w = XWINDOW (window);
13959
13960
13961
13962
13963
13964
13965
13966
13967 if (windows_or_buffers_changed
13968 || w->update_mode_line
13969 || update_mode_lines
13970 || window_buffer_changed (w))
13971 {
13972 struct buffer *prev = current_buffer;
13973 specpdl_ref count = SPECPDL_INDEX ();
13974 Lisp_Object new_tab_bar;
13975 int new_n_tab_bar;
13976
13977
13978
13979
13980 set_buffer_internal_1 (XBUFFER (w->contents));
13981
13982
13983 if (save_match_data)
13984 record_unwind_save_match_data ();
13985
13986
13987 if (NILP (Voverriding_local_map_menu_flag))
13988 {
13989 specbind (Qoverriding_terminal_local_map, Qnil);
13990 specbind (Qoverriding_local_map, Qnil);
13991 }
13992
13993
13994
13995
13996
13997 eassert (EQ (selected_window,
13998
13999
14000 XFRAME (selected_frame)->selected_window));
14001 #ifdef HAVE_WINDOW_SYSTEM
14002 Lisp_Object frame;
14003 record_unwind_protect (restore_selected_window, selected_window);
14004 XSETFRAME (frame, f);
14005 selected_frame = frame;
14006 selected_window = FRAME_SELECTED_WINDOW (f);
14007 #endif
14008
14009
14010 new_tab_bar
14011 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
14012 &new_n_tab_bar);
14013
14014
14015 if (new_n_tab_bar != f->n_tab_bar_items
14016 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14017 {
14018
14019
14020
14021 block_input ();
14022 fset_tab_bar_items (f, new_tab_bar);
14023 f->n_tab_bar_items = new_n_tab_bar;
14024 w->update_mode_line = true;
14025 unblock_input ();
14026 }
14027
14028 unbind_to (count, Qnil);
14029 set_buffer_internal_1 (prev);
14030 }
14031 }
14032 }
14033
14034
14035
14036
14037
14038
14039
14040
14041
14042
14043
14044 static void
14045 display_tab_bar (struct window *w)
14046 {
14047 struct frame *f = XFRAME (WINDOW_FRAME (w));
14048 struct it it;
14049 Lisp_Object items;
14050 int i;
14051
14052
14053 #ifdef HAVE_NTGUI
14054 if (FRAME_W32_P (f))
14055 return;
14056 #endif
14057 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14058 if (FRAME_X_P (f))
14059 return;
14060 #endif
14061
14062 #ifdef HAVE_NS
14063 if (FRAME_NS_P (f))
14064 return;
14065 #endif
14066
14067 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14068 eassert (!FRAME_WINDOW_P (f));
14069 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14070 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14071 TAB_BAR_FACE_ID);
14072 it.first_visible_x = 0;
14073 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14074 #elif defined (HAVE_X_WINDOWS)
14075 if (FRAME_WINDOW_P (f))
14076 {
14077
14078
14079 struct window *tab_w;
14080 tab_w = XWINDOW (f->tab_bar_window);
14081 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14082 TAB_BAR_FACE_ID);
14083 it.first_visible_x = 0;
14084 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14085 }
14086 else
14087 #endif
14088 {
14089
14090
14091 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14092 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14093 TAB_BAR_FACE_ID);
14094 it.first_visible_x = 0;
14095 it.last_visible_x = FRAME_COLS (f);
14096 }
14097
14098
14099
14100
14101 it.paragraph_embedding = L2R;
14102
14103
14104 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14105 {
14106 struct glyph_row *row = it.glyph_row + i;
14107 clear_glyph_row (row);
14108 row->enabled_p = true;
14109 row->full_width_p = true;
14110 row->reversed_p = false;
14111 }
14112
14113
14114 items = it.f->tab_bar_items;
14115 int j;
14116 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14117 {
14118 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14119
14120
14121 if (NILP (string))
14122 break;
14123
14124 if (it.current_x < it.last_visible_x)
14125 display_string (NULL, string, Qnil, 0, 0, &it,
14126 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14127 }
14128
14129
14130 if (it.current_x < it.last_visible_x)
14131 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14132
14133
14134 compute_line_metrics (&it);
14135 }
14136
14137 #ifdef HAVE_WINDOW_SYSTEM
14138
14139
14140
14141
14142
14143 static void
14144 build_desired_tab_bar_string (struct frame *f)
14145 {
14146 int i;
14147 Lisp_Object caption;
14148
14149 caption = Qnil;
14150
14151
14152 fset_desired_tab_bar_string (f, build_string (""));
14153
14154
14155
14156
14157 for (i = 0; i < f->n_tab_bar_items; ++i)
14158 {
14159 #define PROP(IDX) \
14160 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14161
14162 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14163
14164
14165
14166
14167
14168 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14169
14170 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14171 props, caption);
14172
14173 f->desired_tab_bar_string =
14174 concat2 (f->desired_tab_bar_string, caption);
14175
14176 #undef PROP
14177 }
14178 }
14179
14180
14181
14182
14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193 static void
14194 display_tab_bar_line (struct it *it, int height)
14195 {
14196 struct glyph_row *row = it->glyph_row;
14197 int max_x = it->last_visible_x;
14198 struct glyph *last;
14199
14200
14201 clear_glyph_row (row);
14202 row->enabled_p = true;
14203 row->y = it->current_y;
14204
14205
14206
14207 it->start_of_box_run_p = true;
14208
14209 bool enough = false;
14210 while (it->current_x < max_x)
14211 {
14212 int x, n_glyphs_before, i, nglyphs;
14213 struct it it_before;
14214
14215
14216 if (!get_next_display_element (it))
14217 {
14218
14219 if (height < 0 && !it->hpos)
14220 return;
14221 break;
14222 }
14223
14224
14225 n_glyphs_before = row->used[TEXT_AREA];
14226 it_before = *it;
14227
14228 PRODUCE_GLYPHS (it);
14229
14230 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14231 i = 0;
14232 x = it_before.current_x;
14233 while (i < nglyphs)
14234 {
14235 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14236
14237 if (x + glyph->pixel_width > max_x)
14238 {
14239
14240 row->used[TEXT_AREA] = n_glyphs_before;
14241 *it = it_before;
14242
14243
14244
14245 if (n_glyphs_before == 0
14246 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14247 break;
14248 goto out;
14249 }
14250
14251 ++it->hpos;
14252 x += glyph->pixel_width;
14253 ++i;
14254 }
14255
14256 enough = ITERATOR_AT_END_OF_LINE_P (it);
14257 set_iterator_to_next (it, true);
14258
14259
14260 if (enough)
14261 break;
14262 }
14263
14264 out:;
14265
14266 row->displays_text_p = row->used[TEXT_AREA] != 0;
14267
14268
14269
14270
14271
14272
14273
14274 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14275 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14276 it->face_id = DEFAULT_FACE_ID;
14277
14278 extend_face_to_end_of_line (it);
14279 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14280 last->right_box_line_p = true;
14281 if (last == row->glyphs[TEXT_AREA])
14282 last->left_box_line_p = true;
14283
14284
14285 if ((height -= it->max_ascent + it->max_descent) > 0)
14286 {
14287
14288 height %= FRAME_LINE_HEIGHT (it->f);
14289 it->max_ascent += height / 2;
14290 it->max_descent += (height + 1) / 2;
14291 }
14292
14293 compute_line_metrics (it);
14294
14295
14296 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14297 {
14298 row->height = row->phys_height = it->last_visible_y - row->y;
14299 row->visible_height = row->height;
14300 row->ascent = row->phys_ascent = 0;
14301 row->extra_line_spacing = 0;
14302 }
14303
14304 row->full_width_p = true;
14305 row->continued_p = false;
14306 row->truncated_on_left_p = false;
14307 row->truncated_on_right_p = false;
14308
14309 it->current_x = it->hpos = 0;
14310 it->current_y += row->height;
14311 ++it->vpos;
14312 ++it->glyph_row;
14313 }
14314
14315
14316
14317
14318
14319 static int
14320 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14321 {
14322 struct window *w = XWINDOW (f->tab_bar_window);
14323 struct it it;
14324
14325
14326
14327 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14328
14329
14330
14331 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14332 temp_row->reversed_p = false;
14333 it.first_visible_x = 0;
14334 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14335 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14336 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14337 it.paragraph_embedding = L2R;
14338
14339 clear_glyph_row (temp_row);
14340 while (!ITERATOR_AT_END_P (&it))
14341 {
14342 it.glyph_row = temp_row;
14343 display_tab_bar_line (&it, -1);
14344 }
14345 clear_glyph_row (temp_row);
14346
14347
14348 if (n_rows)
14349 *n_rows = it.vpos > 0 ? it.vpos : -1;
14350
14351 if (pixelwise)
14352 return it.current_y;
14353 else
14354 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14355 }
14356
14357 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14358 0, 2, 0,
14359 doc:
14360
14361 )
14362 (Lisp_Object frame, Lisp_Object pixelwise)
14363 {
14364 int height = 0;
14365
14366 struct frame *f = decode_any_frame (frame);
14367
14368 if (WINDOWP (f->tab_bar_window)
14369 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14370 {
14371 update_tab_bar (f, true);
14372 if (f->n_tab_bar_items)
14373 {
14374 build_desired_tab_bar_string (f);
14375 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14376 }
14377 }
14378
14379 return make_fixnum (height);
14380 }
14381
14382
14383
14384
14385 static bool
14386 redisplay_tab_bar (struct frame *f)
14387 {
14388 struct window *w;
14389 struct it it;
14390 struct glyph_row *row;
14391
14392 f->tab_bar_redisplayed = true;
14393
14394
14395
14396
14397
14398 if (!WINDOWP (f->tab_bar_window)
14399 || (w = XWINDOW (f->tab_bar_window),
14400 WINDOW_TOTAL_LINES (w) == 0))
14401 {
14402
14403
14404
14405
14406
14407 f->tab_bar_resized = true;
14408
14409 return false;
14410 }
14411
14412
14413 build_desired_tab_bar_string (f);
14414
14415 int new_nrows;
14416 int new_height = tab_bar_height (f, &new_nrows, true);
14417
14418 if (f->n_tab_bar_rows == 0)
14419 {
14420 f->n_tab_bar_rows = new_nrows;
14421 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14422 frame_default_tab_bar_height = new_height;
14423 }
14424
14425
14426
14427 if (new_nrows > f->n_tab_bar_rows
14428 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14429 && !f->minimize_tab_bar_window_p
14430 && new_height > WINDOW_PIXEL_HEIGHT (w))
14431 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14432 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14433 {
14434 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14435 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14436 if (new_nrows != f->n_tab_bar_rows)
14437 f->n_tab_bar_rows = new_nrows;
14438 clear_glyph_matrix (w->desired_matrix);
14439 f->fonts_changed = true;
14440 return true;
14441 }
14442
14443
14444 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14445 it.first_visible_x = 0;
14446 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14447 row = it.glyph_row;
14448 row->reversed_p = false;
14449 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14450 STRING_MULTIBYTE (f->desired_tab_bar_string));
14451
14452
14453
14454
14455
14456
14457
14458 it.paragraph_embedding = L2R;
14459
14460
14461
14462 if (f->n_tab_bar_rows > 0)
14463 {
14464 int border, rows, height, extra;
14465
14466 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14467 border = XFIXNUM (Vtab_bar_border);
14468 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14469 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14470 else if (EQ (Vtab_bar_border, Qborder_width))
14471 border = f->border_width;
14472 else
14473 border = 0;
14474 if (border < 0)
14475 border = 0;
14476
14477 rows = f->n_tab_bar_rows;
14478 height = max (1, (it.last_visible_y - border) / rows);
14479 extra = it.last_visible_y - border - height * rows;
14480
14481 while (it.current_y < it.last_visible_y)
14482 {
14483 int h = 0;
14484 if (extra > 0 && rows-- > 0)
14485 {
14486 h = (extra + rows - 1) / rows;
14487 extra -= h;
14488 }
14489 display_tab_bar_line (&it, height + h);
14490 }
14491 }
14492 else
14493 {
14494 while (it.current_y < it.last_visible_y)
14495 display_tab_bar_line (&it, 0);
14496 }
14497
14498
14499
14500 w->desired_matrix->no_scrolling_p = true;
14501 w->must_be_updated_p = true;
14502
14503 if (!NILP (Vauto_resize_tab_bars))
14504 {
14505 bool change_height_p = false;
14506
14507
14508
14509 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14510 change_height_p = true;
14511
14512
14513
14514
14515
14516 row = it.glyph_row - 1;
14517
14518
14519
14520
14521 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14522 && row->height >= FRAME_LINE_HEIGHT (f))
14523 change_height_p = true;
14524
14525
14526
14527 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14528 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14529 change_height_p = true;
14530
14531
14532
14533 if (change_height_p)
14534 {
14535 int nrows;
14536 int new_height = tab_bar_height (f, &nrows, true);
14537
14538 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14539 && !f->minimize_tab_bar_window_p)
14540 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14541 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14542 f->minimize_tab_bar_window_p = false;
14543
14544 if (change_height_p)
14545 {
14546 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14547 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14548 frame_default_tab_bar_height = new_height;
14549 clear_glyph_matrix (w->desired_matrix);
14550 f->n_tab_bar_rows = nrows;
14551 f->fonts_changed = true;
14552
14553 return true;
14554 }
14555 }
14556 }
14557
14558 f->minimize_tab_bar_window_p = false;
14559 return false;
14560 }
14561
14562
14563
14564
14565
14566
14567
14568 static bool
14569 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14570 int *prop_idx, bool *close_p)
14571 {
14572 Lisp_Object prop;
14573 ptrdiff_t charpos;
14574
14575
14576
14577
14578 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14579 charpos = max (0, charpos);
14580
14581
14582
14583
14584 prop = Fget_text_property (make_fixnum (charpos),
14585 Qmenu_item, f->current_tab_bar_string);
14586 if (! FIXNUMP (prop))
14587 return false;
14588
14589 *prop_idx = XFIXNUM (prop);
14590
14591 if (close_p)
14592 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14593 Qclose_tab,
14594 f->current_tab_bar_string));
14595
14596 return true;
14597 }
14598
14599
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619 static int
14620 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14621 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14622 {
14623 struct window *w = XWINDOW (f->tab_bar_window);
14624 int area;
14625
14626
14627 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14628 if (*glyph == NULL)
14629 return -1;
14630
14631
14632
14633 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14634 return -1;
14635
14636 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14637 }
14638
14639
14640
14641
14642
14643
14644
14645 int
14646 get_tab_bar_item_kbd (struct frame *f, int x, int y, int *prop_idx,
14647 bool *close_p)
14648 {
14649 struct window *w;
14650 int area, vpos, hpos;
14651 struct glyph *glyph;
14652
14653 w = XWINDOW (f->tab_bar_window);
14654
14655
14656 frame_to_window_pixel_xy (w, &x, &y);
14657
14658
14659 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, 0,
14660 0, &area);
14661 if (glyph == NULL)
14662 return -1;
14663
14664
14665
14666 if (!tab_bar_item_info (f, glyph, prop_idx, close_p))
14667 return -1;
14668
14669 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14670 }
14671
14672
14673
14674
14675
14676
14677
14678 Lisp_Object
14679 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14680 int modifiers)
14681 {
14682 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14683 struct window *w = XWINDOW (f->tab_bar_window);
14684 int hpos, vpos, prop_idx;
14685 bool close_p;
14686 struct glyph *glyph;
14687 Lisp_Object enabled_p;
14688 int ts;
14689
14690 frame_to_window_pixel_xy (w, &x, &y);
14691 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14692 if (ts == -1)
14693 return Fcons (Qtab_bar, Qnil);
14694
14695
14696 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14697 if (NILP (enabled_p))
14698 return Qnil;
14699
14700 if (down_p)
14701 {
14702
14703 if (!NILP (Vmouse_highlight))
14704 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14705 f->last_tab_bar_item = prop_idx;
14706 }
14707 else
14708 {
14709
14710 if (!NILP (Vmouse_highlight))
14711 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14712 f->last_tab_bar_item = -1;
14713 }
14714
14715 Lisp_Object caption =
14716 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14717
14718 AUTO_LIST2 (props, Qmenu_item,
14719 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14720 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14721 close_p ? Qt : Qnil));
14722
14723 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14724 props, caption);
14725
14726 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14727 }
14728
14729
14730
14731
14732
14733
14734 static void
14735 note_tab_bar_highlight (struct frame *f, int x, int y)
14736 {
14737 Lisp_Object window = f->tab_bar_window;
14738 struct window *w = XWINDOW (window);
14739 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14740 int hpos, vpos;
14741 struct glyph *glyph;
14742 struct glyph_row *row;
14743 int i;
14744 Lisp_Object enabled_p;
14745 int prop_idx;
14746 bool close_p;
14747 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14748 int rc;
14749
14750
14751
14752 if (x <= 0 || y <= 0)
14753 {
14754 clear_mouse_face (hlinfo);
14755 return;
14756 }
14757
14758 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14759 if (rc < 0)
14760 {
14761
14762 clear_mouse_face (hlinfo);
14763 return;
14764 }
14765 else if (rc == 0)
14766
14767 goto set_help_echo;
14768
14769 clear_mouse_face (hlinfo);
14770
14771 bool mouse_down_p = false;
14772
14773
14774
14775
14776
14777 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14778 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14779 && f == dpyinfo->last_mouse_frame);
14780
14781 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14782 && f->last_tab_bar_item != -1)
14783 return;
14784 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14785
14786
14787 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14788 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14789 {
14790
14791
14792 row = MATRIX_ROW (w->current_matrix, vpos);
14793 for (i = x = 0; i < hpos; ++i)
14794 x += row->glyphs[TEXT_AREA][i].pixel_width;
14795
14796
14797 hlinfo->mouse_face_beg_col = hpos;
14798 hlinfo->mouse_face_beg_row = vpos;
14799 hlinfo->mouse_face_beg_x = x;
14800 hlinfo->mouse_face_past_end = false;
14801
14802 hlinfo->mouse_face_end_col = hpos + 1;
14803 hlinfo->mouse_face_end_row = vpos;
14804 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14805 hlinfo->mouse_face_window = window;
14806 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14807
14808
14809 show_mouse_face (hlinfo, draw);
14810 }
14811
14812 set_help_echo:
14813
14814
14815
14816 help_echo_object = help_echo_window = Qnil;
14817 help_echo_pos = -1;
14818 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14819 if (NILP (help_echo_string))
14820 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14821 }
14822
14823 #endif
14824
14825
14826 static Lisp_Object
14827 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14828 {
14829 ptrdiff_t clen = 0;
14830
14831 for (int i = 0; i < f->n_tab_bar_items; i++)
14832 {
14833 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14834 + TAB_BAR_ITEM_CAPTION));
14835 if (NILP (caption))
14836 return Qnil;
14837 clen += SCHARS (caption);
14838 if (x < clen)
14839 {
14840 *prop_idx = i;
14841 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14842 - (clen - x)),
14843 Qclose_tab,
14844 caption));
14845 return caption;
14846 }
14847 }
14848 return Qnil;
14849 }
14850
14851
14852
14853
14854
14855
14856 Lisp_Object
14857 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14858 struct input_event *event)
14859 {
14860
14861 if (y < FRAME_MENU_BAR_LINES (f)
14862 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14863 return Qnil;
14864
14865
14866 int prop_idx;
14867 bool close_p;
14868 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14869
14870 if (NILP (caption))
14871 return Qnil;
14872
14873 if (NILP (AREF (f->tab_bar_items,
14874 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14875 return Qnil;
14876
14877 if (down_p)
14878 f->last_tab_bar_item = prop_idx;
14879 else
14880 f->last_tab_bar_item = -1;
14881
14882 caption = Fcopy_sequence (caption);
14883
14884 AUTO_LIST2 (props, Qmenu_item,
14885 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14886 + TAB_BAR_ITEM_KEY),
14887 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14888 + TAB_BAR_ITEM_BINDING),
14889 close_p ? Qt : Qnil));
14890
14891 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14892 props, caption);
14893
14894 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14895 }
14896
14897
14898
14899
14900
14901
14902
14903 #ifdef HAVE_WINDOW_SYSTEM
14904
14905
14906
14907
14908
14909
14910 static void
14911 update_tool_bar (struct frame *f, bool save_match_data)
14912 {
14913 #ifdef HAVE_EXT_TOOL_BAR
14914 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14915 #else
14916 bool do_update = (WINDOWP (f->tool_bar_window)
14917 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14918 #endif
14919
14920 if (do_update)
14921 {
14922 Lisp_Object window;
14923 struct window *w;
14924
14925 window = FRAME_SELECTED_WINDOW (f);
14926 w = XWINDOW (window);
14927
14928
14929
14930
14931
14932
14933
14934
14935 if (windows_or_buffers_changed
14936 || w->update_mode_line
14937 || update_mode_lines
14938 || window_buffer_changed (w))
14939 {
14940 struct buffer *prev = current_buffer;
14941 specpdl_ref count = SPECPDL_INDEX ();
14942 Lisp_Object frame, new_tool_bar;
14943 int new_n_tool_bar;
14944
14945
14946
14947
14948 set_buffer_internal_1 (XBUFFER (w->contents));
14949
14950
14951 if (save_match_data)
14952 record_unwind_save_match_data ();
14953
14954
14955 if (NILP (Voverriding_local_map_menu_flag))
14956 {
14957 specbind (Qoverriding_terminal_local_map, Qnil);
14958 specbind (Qoverriding_local_map, Qnil);
14959 }
14960
14961
14962
14963
14964
14965 eassert (EQ (selected_window,
14966
14967
14968 XFRAME (selected_frame)->selected_window));
14969 record_unwind_protect (restore_selected_window, selected_window);
14970 XSETFRAME (frame, f);
14971 selected_frame = frame;
14972 selected_window = FRAME_SELECTED_WINDOW (f);
14973
14974
14975 new_tool_bar
14976 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14977 &new_n_tool_bar);
14978
14979
14980 if (new_n_tool_bar != f->n_tool_bar_items
14981 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14982 {
14983
14984
14985
14986 block_input ();
14987 fset_tool_bar_items (f, new_tool_bar);
14988 f->n_tool_bar_items = new_n_tool_bar;
14989 w->update_mode_line = true;
14990 unblock_input ();
14991 }
14992
14993 unbind_to (count, Qnil);
14994 set_buffer_internal_1 (prev);
14995 }
14996 }
14997 }
14998
14999 #ifndef HAVE_EXT_TOOL_BAR
15000
15001
15002
15003
15004
15005
15006
15007
15008 static void
15009 build_desired_tool_bar_string (struct frame *f)
15010 {
15011 int i, size, size_needed;
15012 Lisp_Object image, plist;
15013
15014 image = plist = Qnil;
15015
15016
15017
15018
15019
15020 size = (STRINGP (f->desired_tool_bar_string)
15021 ? SCHARS (f->desired_tool_bar_string)
15022 : 0);
15023
15024
15025 size_needed = f->n_tool_bar_items;
15026
15027
15028
15029 if (size < size_needed || NILP (f->desired_tool_bar_string))
15030
15031
15032 fset_desired_tool_bar_string (f, make_uninit_string (size_needed));
15033 else
15034 {
15035 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
15036 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
15037 props, f->desired_tool_bar_string);
15038 }
15039
15040 f->tool_bar_wraps_p = false;
15041
15042
15043
15044
15045 for (i = 0; i < f->n_tool_bar_items; ++i)
15046 {
15047 #define PROP(IDX) \
15048 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
15049
15050 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
15051 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
15052 int hmargin, vmargin, relief, idx, end;
15053
15054 if (!NILP (PROP (TOOL_BAR_ITEM_WRAP)))
15055 {
15056
15057
15058 SSET (f->desired_tool_bar_string, i, '\n');
15059
15060
15061
15062 f->tool_bar_wraps_p = true;
15063 continue;
15064 }
15065
15066
15067 SSET (f->desired_tool_bar_string, i, ' ');
15068
15069
15070
15071 image = PROP (TOOL_BAR_ITEM_IMAGES);
15072 if (VECTORP (image))
15073 {
15074 if (enabled_p)
15075 idx = (selected_p
15076 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
15077 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
15078 else
15079 idx = (selected_p
15080 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15081 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15082
15083 eassert (ASIZE (image) >= idx);
15084 image = AREF (image, idx);
15085 }
15086 else
15087 idx = -1;
15088
15089
15090 if (!valid_image_p (image))
15091 continue;
15092
15093
15094 plist = Fcopy_sequence (XCDR (image));
15095
15096
15097 relief = (tool_bar_button_relief >= 0
15098 ? min (tool_bar_button_relief,
15099 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15100 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15101 hmargin = vmargin = relief;
15102
15103 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15104 INT_MAX - max (hmargin, vmargin)))
15105 {
15106 hmargin += XFIXNAT (Vtool_bar_button_margin);
15107 vmargin += XFIXNAT (Vtool_bar_button_margin);
15108 }
15109 else if (CONSP (Vtool_bar_button_margin))
15110 {
15111 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15112 INT_MAX - hmargin))
15113 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15114
15115 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15116 INT_MAX - vmargin))
15117 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15118 }
15119
15120 if (auto_raise_tool_bar_buttons_p)
15121 {
15122
15123
15124 if (selected_p)
15125 {
15126 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15127 hmargin -= relief;
15128 vmargin -= relief;
15129 }
15130 }
15131 else
15132 {
15133
15134
15135
15136 plist = plist_put (plist, QCrelief,
15137 (selected_p
15138 ? make_fixnum (-relief)
15139 : make_fixnum (relief)));
15140 hmargin -= relief;
15141 vmargin -= relief;
15142 }
15143
15144
15145 if (hmargin || vmargin)
15146 {
15147 if (hmargin == vmargin)
15148 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15149 else
15150 plist = plist_put (plist, QCmargin,
15151 Fcons (make_fixnum (hmargin),
15152 make_fixnum (vmargin)));
15153 }
15154
15155
15156
15157
15158 if (!enabled_p && idx < 0)
15159 plist = plist_put (plist, QCconversion, Qdisabled);
15160
15161
15162
15163
15164
15165 image = Fcons (Qimage, plist);
15166 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15167 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15168
15169
15170
15171
15172 if (i + 1 == f->n_tool_bar_items)
15173 end = SCHARS (f->desired_tool_bar_string);
15174 else
15175 end = i + 1;
15176 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15177 props, f->desired_tool_bar_string);
15178 #undef PROP
15179 }
15180
15181
15182
15183
15184
15185
15186
15187 for (; i < size; ++i)
15188
15189 SSET (f->desired_tool_bar_string, i, ' ');
15190 }
15191
15192
15193
15194
15195
15196
15197
15198
15199
15200
15201
15202
15203
15204
15205
15206
15207
15208 static void
15209 display_tool_bar_line (struct it *it, int height)
15210 {
15211 struct glyph_row *row = it->glyph_row;
15212 int max_x = it->last_visible_x;
15213 struct glyph *last;
15214
15215
15216 clear_glyph_row (row);
15217 row->enabled_p = true;
15218 row->y = it->current_y;
15219
15220
15221
15222 it->start_of_box_run_p = true;
15223
15224 while (it->current_x < max_x)
15225 {
15226 int x, n_glyphs_before, i, nglyphs;
15227 struct it it_before;
15228
15229
15230 if (!get_next_display_element (it))
15231 {
15232
15233 if (height < 0 && !it->hpos)
15234 return;
15235 break;
15236 }
15237
15238
15239 n_glyphs_before = row->used[TEXT_AREA];
15240 it_before = *it;
15241
15242 PRODUCE_GLYPHS (it);
15243
15244 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15245 i = 0;
15246 x = it_before.current_x;
15247 while (i < nglyphs)
15248 {
15249 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15250
15251 if (x + glyph->pixel_width > max_x)
15252 {
15253
15254 row->used[TEXT_AREA] = n_glyphs_before;
15255 *it = it_before;
15256
15257
15258
15259 if (n_glyphs_before == 0
15260 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15261 break;
15262 goto out;
15263 }
15264
15265 ++it->hpos;
15266 x += glyph->pixel_width;
15267 ++i;
15268 }
15269
15270
15271
15272
15273
15274
15275 if (ITERATOR_AT_END_OF_LINE_P (it))
15276 {
15277 reseat_at_next_visible_line_start (it, false);
15278 break;
15279 }
15280
15281 if (ITERATOR_AT_END_P (it))
15282 break;
15283
15284 set_iterator_to_next (it, true);
15285 }
15286
15287 out:;
15288
15289 row->displays_text_p = row->used[TEXT_AREA] != 0;
15290
15291
15292
15293
15294
15295
15296
15297 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15298 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15299 it->face_id = DEFAULT_FACE_ID;
15300
15301 extend_face_to_end_of_line (it);
15302 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15303 last->right_box_line_p = true;
15304 if (last == row->glyphs[TEXT_AREA])
15305 last->left_box_line_p = true;
15306
15307
15308 if (height != -1
15309 && (height -= it->max_ascent + it->max_descent) > 0)
15310 {
15311
15312 height %= FRAME_LINE_HEIGHT (it->f);
15313 it->max_ascent += height / 2;
15314 it->max_descent += (height + 1) / 2;
15315 }
15316
15317 compute_line_metrics (it);
15318
15319
15320 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15321 {
15322 row->height = row->phys_height = it->last_visible_y - row->y;
15323 row->visible_height = row->height;
15324 row->ascent = row->phys_ascent = 0;
15325 row->extra_line_spacing = 0;
15326 }
15327
15328 row->full_width_p = true;
15329 row->continued_p = false;
15330 row->truncated_on_left_p = false;
15331 row->truncated_on_right_p = false;
15332
15333 it->current_x = it->hpos = 0;
15334 it->current_y += row->height;
15335 ++it->vpos;
15336 ++it->glyph_row;
15337 }
15338
15339
15340
15341
15342
15343
15344 static int
15345 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15346 {
15347 struct window *w = XWINDOW (f->tool_bar_window);
15348 struct it it;
15349
15350
15351
15352 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15353
15354
15355
15356 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15357 temp_row->reversed_p = false;
15358 it.first_visible_x = 0;
15359 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15360 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15361 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15362 it.paragraph_embedding = L2R;
15363
15364 while (!ITERATOR_AT_END_P (&it))
15365 {
15366 clear_glyph_row (temp_row);
15367 it.glyph_row = temp_row;
15368 display_tool_bar_line (&it, -1);
15369 }
15370 clear_glyph_row (temp_row);
15371
15372
15373 if (n_rows)
15374 *n_rows = it.vpos > 0 ? it.vpos : -1;
15375
15376 if (pixelwise)
15377 return it.current_y;
15378 else
15379 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15380 }
15381
15382 #endif
15383
15384 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15385 0, 2, 0,
15386 doc:
15387
15388 )
15389 (Lisp_Object frame, Lisp_Object pixelwise)
15390 {
15391 int height = 0;
15392
15393 #ifndef HAVE_EXT_TOOL_BAR
15394 struct frame *f = decode_any_frame (frame);
15395
15396 if (WINDOWP (f->tool_bar_window)
15397 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15398 {
15399 update_tool_bar (f, true);
15400 if (f->n_tool_bar_items)
15401 {
15402 build_desired_tool_bar_string (f);
15403 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15404 }
15405 }
15406 #endif
15407
15408 return make_fixnum (height);
15409 }
15410
15411 #ifndef HAVE_EXT_TOOL_BAR
15412
15413
15414
15415 static bool
15416 redisplay_tool_bar (struct frame *f)
15417 {
15418 struct window *w;
15419 struct it it;
15420 struct glyph_row *row;
15421 bool change_height_p;
15422
15423 change_height_p = false;
15424 f->tool_bar_redisplayed = true;
15425
15426
15427
15428
15429
15430 if (!WINDOWP (f->tool_bar_window)
15431 || (w = XWINDOW (f->tool_bar_window),
15432 WINDOW_TOTAL_LINES (w) == 0))
15433 {
15434
15435
15436
15437
15438
15439 f->tool_bar_resized = true;
15440
15441 return false;
15442 }
15443
15444
15445 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15446 it.first_visible_x = 0;
15447 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15448 row = it.glyph_row;
15449 row->reversed_p = false;
15450
15451
15452 build_desired_tool_bar_string (f);
15453 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15454 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15455
15456
15457
15458
15459
15460
15461
15462 it.paragraph_embedding = L2R;
15463
15464 if (f->n_tool_bar_rows == 0)
15465 {
15466 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15467
15468 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15469 {
15470 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15471 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15472 frame_default_tool_bar_height = new_height;
15473
15474 clear_glyph_matrix (w->desired_matrix);
15475 f->fonts_changed = true;
15476
15477
15478
15479
15480
15481
15482
15483 resize_frame_windows (f, FRAME_INNER_HEIGHT (f), false);
15484
15485 return true;
15486 }
15487 }
15488
15489
15490
15491 if (f->n_tool_bar_rows > 0)
15492 {
15493 int border, rows, height, extra;
15494
15495 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15496 border = XFIXNUM (Vtool_bar_border);
15497 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15498 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15499 else if (EQ (Vtool_bar_border, Qborder_width))
15500 border = f->border_width;
15501 else
15502 border = 0;
15503 if (border < 0)
15504 border = 0;
15505
15506 rows = f->n_tool_bar_rows;
15507
15508 if (f->tool_bar_wraps_p)
15509 {
15510
15511
15512
15513 while (!ITERATOR_AT_END_P (&it))
15514 display_tool_bar_line (&it, -1);
15515
15516
15517
15518
15519
15520
15521 if (it.current_y != it.last_visible_y)
15522 change_height_p = true;
15523 }
15524 else
15525 {
15526 height = max (1, (it.last_visible_y - border) / rows);
15527 extra = it.last_visible_y - border - height * rows;
15528
15529 while (it.current_y < it.last_visible_y)
15530 {
15531 int h = 0;
15532 if (extra > 0 && rows-- > 0)
15533 {
15534 h = (extra + rows - 1) / rows;
15535 extra -= h;
15536 }
15537
15538 display_tool_bar_line (&it, height + h);
15539 }
15540 }
15541 }
15542 else
15543 {
15544 while (it.current_y < it.last_visible_y)
15545 display_tool_bar_line (&it, 0);
15546 }
15547
15548
15549
15550 w->desired_matrix->no_scrolling_p = true;
15551 w->must_be_updated_p = true;
15552
15553 if (!NILP (Vauto_resize_tool_bars))
15554 {
15555
15556
15557 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15558 change_height_p = true;
15559
15560
15561
15562
15563
15564 row = it.glyph_row - 1;
15565
15566
15567
15568
15569 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15570 && row->height >= FRAME_LINE_HEIGHT (f))
15571 change_height_p = true;
15572
15573
15574
15575 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15576 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15577 change_height_p = true;
15578
15579
15580
15581 if (change_height_p)
15582 {
15583 int nrows;
15584 int new_height = tool_bar_height (f, &nrows, true);
15585
15586 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15587 && !f->minimize_tool_bar_window_p)
15588 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15589 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15590 f->minimize_tool_bar_window_p = false;
15591
15592 if (change_height_p)
15593 {
15594 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15595 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15596 frame_default_tool_bar_height = new_height;
15597 clear_glyph_matrix (w->desired_matrix);
15598 f->n_tool_bar_rows = nrows;
15599 f->fonts_changed = true;
15600
15601 return true;
15602 }
15603 }
15604 }
15605
15606 f->minimize_tool_bar_window_p = false;
15607
15608 return false;
15609 }
15610
15611
15612
15613
15614
15615
15616 static bool
15617 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15618 {
15619 Lisp_Object prop;
15620 ptrdiff_t charpos;
15621
15622
15623
15624
15625 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15626 charpos = max (0, charpos);
15627
15628
15629
15630
15631 prop = Fget_text_property (make_fixnum (charpos),
15632 Qmenu_item, f->current_tool_bar_string);
15633 if (! FIXNUMP (prop))
15634 return false;
15635 *prop_idx = XFIXNUM (prop);
15636 return true;
15637 }
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650 static int
15651 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15652 int *hpos, int *vpos, int *prop_idx)
15653 {
15654 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15655 struct window *w = XWINDOW (f->tool_bar_window);
15656 int area;
15657
15658
15659 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15660 if (*glyph == NULL)
15661 return -1;
15662
15663
15664
15665 if (!tool_bar_item_info (f, *glyph, prop_idx))
15666 return -1;
15667
15668
15669 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15670 && *vpos >= hlinfo->mouse_face_beg_row
15671 && *vpos <= hlinfo->mouse_face_end_row
15672 && (*vpos > hlinfo->mouse_face_beg_row
15673 || *hpos >= hlinfo->mouse_face_beg_col)
15674 && (*vpos < hlinfo->mouse_face_end_row
15675 || *hpos < hlinfo->mouse_face_end_col
15676 || hlinfo->mouse_face_past_end))
15677 return 0;
15678
15679 return 1;
15680 }
15681
15682
15683
15684
15685
15686
15687
15688
15689 void
15690 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15691 int modifiers, Lisp_Object device)
15692 {
15693 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15694 struct window *w = XWINDOW (f->tool_bar_window);
15695 int hpos, vpos, prop_idx;
15696 struct glyph *glyph;
15697 Lisp_Object enabled_p;
15698 int ts;
15699
15700
15701
15702
15703
15704
15705
15706
15707 frame_to_window_pixel_xy (w, &x, &y);
15708 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15709 if (ts == -1
15710 || (ts != 0 && !NILP (Vmouse_highlight)))
15711 return;
15712
15713
15714
15715
15716 if (NILP (Vmouse_highlight) && !down_p)
15717 prop_idx = f->last_tool_bar_item;
15718
15719
15720 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15721 if (NILP (enabled_p))
15722 return;
15723
15724 if (down_p)
15725 {
15726
15727 if (!NILP (Vmouse_highlight))
15728 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15729 f->last_tool_bar_item = prop_idx;
15730 }
15731 else
15732 {
15733 Lisp_Object key, frame;
15734 struct input_event event;
15735 EVENT_INIT (event);
15736
15737
15738 if (!NILP (Vmouse_highlight))
15739 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15740
15741 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15742
15743 XSETFRAME (frame, f);
15744 event.kind = TOOL_BAR_EVENT;
15745 event.frame_or_window = frame;
15746 event.arg = key;
15747 event.modifiers = modifiers;
15748 event.device = device;
15749 kbd_buffer_store_event (&event);
15750 f->last_tool_bar_item = -1;
15751 }
15752 }
15753
15754 void
15755 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15756 int modifiers)
15757 {
15758 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15759 }
15760
15761
15762
15763
15764
15765 static void
15766 note_tool_bar_highlight (struct frame *f, int x, int y)
15767 {
15768 Lisp_Object window = f->tool_bar_window;
15769 struct window *w = XWINDOW (window);
15770 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15771 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15772 int hpos, vpos;
15773 struct glyph *glyph;
15774 struct glyph_row *row;
15775 int i;
15776 Lisp_Object enabled_p;
15777 int prop_idx;
15778 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15779 bool mouse_down_p;
15780 int rc;
15781
15782
15783
15784 if (x <= 0 || y <= 0)
15785 {
15786 clear_mouse_face (hlinfo);
15787 return;
15788 }
15789
15790 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15791 if (rc < 0)
15792 {
15793
15794 clear_mouse_face (hlinfo);
15795 return;
15796 }
15797 else if (rc == 0)
15798
15799 goto set_help_echo;
15800
15801 clear_mouse_face (hlinfo);
15802
15803
15804 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15805 && f == dpyinfo->last_mouse_frame);
15806
15807 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15808 return;
15809
15810 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15811
15812
15813 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15814 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15815 {
15816
15817
15818 row = MATRIX_ROW (w->current_matrix, vpos);
15819 for (i = x = 0; i < hpos; ++i)
15820 x += row->glyphs[TEXT_AREA][i].pixel_width;
15821
15822
15823 hlinfo->mouse_face_beg_col = hpos;
15824 hlinfo->mouse_face_beg_row = vpos;
15825 hlinfo->mouse_face_beg_x = x;
15826 hlinfo->mouse_face_past_end = false;
15827
15828 hlinfo->mouse_face_end_col = hpos + 1;
15829 hlinfo->mouse_face_end_row = vpos;
15830 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15831 hlinfo->mouse_face_window = window;
15832 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15833
15834
15835 show_mouse_face (hlinfo, draw);
15836 }
15837
15838 set_help_echo:
15839
15840
15841
15842 help_echo_object = help_echo_window = Qnil;
15843 help_echo_pos = -1;
15844 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15845 if (NILP (help_echo_string))
15846 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15847 }
15848
15849 #endif
15850
15851 #endif
15852
15853
15854
15855
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865 static bool
15866 hscroll_window_tree (Lisp_Object window)
15867 {
15868 bool hscrolled_p = false;
15869 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15870 int hscroll_step_abs = 0;
15871 double hscroll_step_rel = 0;
15872
15873 if (hscroll_relative_p)
15874 {
15875 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15876 if (hscroll_step_rel < 0)
15877 {
15878 hscroll_relative_p = false;
15879 hscroll_step_abs = 0;
15880 }
15881 }
15882 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15883 {
15884 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15885 if (hscroll_step_abs < 0)
15886 hscroll_step_abs = 0;
15887 }
15888 else
15889 hscroll_step_abs = 0;
15890
15891 while (WINDOWP (window))
15892 {
15893 struct window *w = XWINDOW (window);
15894
15895 if (WINDOWP (w->contents))
15896 hscrolled_p |= hscroll_window_tree (w->contents);
15897 else if (w->cursor.vpos >= 0
15898
15899
15900
15901
15902
15903
15904 && !(w == XWINDOW (echo_area_window)
15905 && !NILP (echo_area_buffer[0])))
15906 {
15907 int h_margin;
15908 int text_area_width;
15909 struct glyph_row *cursor_row;
15910 struct glyph_row *bottom_row;
15911
15912 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15913 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15914 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15915 else
15916 cursor_row = bottom_row - 1;
15917
15918 if (!cursor_row->enabled_p)
15919 {
15920 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15921 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15922 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15923 else
15924 cursor_row = bottom_row - 1;
15925 }
15926 bool row_r2l_p = cursor_row->reversed_p;
15927 bool hscl = hscrolling_current_line_p (w);
15928 int x_offset = 0;
15929
15930
15931 if (!NILP (Vdisplay_line_numbers))
15932 {
15933 struct glyph *g;
15934 if (!row_r2l_p)
15935 {
15936 for (g = cursor_row->glyphs[TEXT_AREA];
15937 g < cursor_row->glyphs[TEXT_AREA]
15938 + cursor_row->used[TEXT_AREA];
15939 g++)
15940 {
15941 if (!(NILP (g->object) && g->charpos < 0))
15942 break;
15943 x_offset += g->pixel_width;
15944 }
15945 }
15946 else
15947 {
15948 for (g = cursor_row->glyphs[TEXT_AREA]
15949 + cursor_row->used[TEXT_AREA];
15950 g > cursor_row->glyphs[TEXT_AREA];
15951 g--)
15952 {
15953 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15954 break;
15955 x_offset += (g - 1)->pixel_width;
15956 }
15957 }
15958 }
15959 if (cursor_row->truncated_on_left_p)
15960 {
15961
15962 struct frame *f = XFRAME (WINDOW_FRAME (w));
15963 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15964 }
15965
15966 text_area_width = window_box_width (w, TEXT_AREA);
15967
15968
15969 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15970 * WINDOW_FRAME_COLUMN_WIDTH (w));
15971
15972
15973
15974 if (w->suspend_auto_hscroll
15975 && NILP (Fequal (Fwindow_point (window),
15976 Fwindow_old_point (window))))
15977 {
15978 w->suspend_auto_hscroll = false;
15979
15980
15981
15982
15983 if (w->min_hscroll == 0 && w->hscroll > 0
15984 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15985 Qcurrent_line))
15986 SET_FRAME_GARBAGED (XFRAME (w->frame));
15987 }
15988
15989
15990 Fset_marker (w->old_pointm,
15991 ((w == XWINDOW (selected_window))
15992 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15993 : Fmarker_position (w->pointm)),
15994 w->contents);
15995
15996 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15997 && !w->suspend_auto_hscroll
15998
15999
16000
16001
16002
16003
16004 && (CHARPOS (cursor_row->start.pos)
16005 >= BUF_BEG (XBUFFER (w->contents)))
16006
16007
16008
16009
16010 && ((!row_r2l_p
16011 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
16012 || (cursor_row->enabled_p
16013 && cursor_row->truncated_on_right_p
16014 && (w->cursor.x >= text_area_width - h_margin))))
16015
16016
16017
16018
16019
16020
16021 || (row_r2l_p
16022 && ((cursor_row->enabled_p
16023
16024
16025
16026 && cursor_row->truncated_on_right_p
16027 && w->cursor.x <= h_margin)
16028 || (w->hscroll
16029 && (w->cursor.x >= (text_area_width - h_margin
16030 - x_offset)))))
16031
16032
16033
16034
16035
16036 || (hscl
16037 && w->hscroll != w->min_hscroll
16038 && !cursor_row->truncated_on_left_p)))
16039 {
16040 struct it it;
16041 ptrdiff_t hscroll;
16042 struct buffer *saved_current_buffer;
16043 ptrdiff_t pt;
16044 int wanted_x;
16045
16046
16047 saved_current_buffer = current_buffer;
16048 current_buffer = XBUFFER (w->contents);
16049
16050 if (w == XWINDOW (selected_window))
16051 pt = PT;
16052 else
16053 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
16054
16055
16056
16057 init_to_row_start (&it, w, cursor_row);
16058 if (hscl)
16059 it.first_visible_x = window_hscroll_limited (w, it.f)
16060 * FRAME_COLUMN_WIDTH (it.f);
16061 it.last_visible_x = DISP_INFINITY;
16062
16063 ptrdiff_t nchars = pt - IT_CHARPOS (it);
16064 if (current_buffer->long_line_optimizations_p
16065 && nchars > large_hscroll_threshold)
16066 {
16067
16068
16069
16070
16071 fast_move_it_horizontally (&it, nchars);
16072 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
16073 }
16074 else
16075 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
16076
16077
16078
16079
16080
16081
16082 if (it.method == GET_FROM_STRING && pt > 1)
16083 {
16084 init_to_row_start (&it, w, cursor_row);
16085 if (hscl)
16086 it.first_visible_x = (window_hscroll_limited (w, it.f)
16087 * FRAME_COLUMN_WIDTH (it.f));
16088 if (current_buffer->long_line_optimizations_p
16089 && nchars > large_hscroll_threshold)
16090 {
16091 fast_move_it_horizontally (&it, nchars - 1);
16092 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
16093 }
16094 else
16095 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
16096 }
16097 current_buffer = saved_current_buffer;
16098
16099
16100 if (!hscroll_relative_p && hscroll_step_abs == 0)
16101 hscroll = max (0, (it.current_x
16102 - (ITERATOR_AT_END_OF_LINE_P (&it)
16103 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
16104 : (text_area_width / 2))))
16105 / FRAME_COLUMN_WIDTH (it.f);
16106 else if ((!row_r2l_p
16107 && w->cursor.x >= text_area_width - h_margin)
16108 || (row_r2l_p && w->cursor.x <= h_margin))
16109 {
16110 if (hscroll_relative_p)
16111 wanted_x = text_area_width * (1 - hscroll_step_rel)
16112 - h_margin;
16113 else
16114 wanted_x = text_area_width
16115 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16116 - h_margin;
16117 hscroll
16118 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16119 }
16120 else
16121 {
16122 if (hscroll_relative_p)
16123 wanted_x =
16124 text_area_width * hscroll_step_rel + h_margin + x_offset;
16125 else
16126 wanted_x =
16127 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
16128 + h_margin + x_offset;
16129 hscroll
16130 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
16131 }
16132 hscroll = max (hscroll, w->min_hscroll);
16133
16134
16135
16136
16137 if (w->hscroll != hscroll
16138
16139
16140
16141
16142 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16143 {
16144 struct buffer *b = XBUFFER (w->contents);
16145 b->prevent_redisplay_optimizations_p = true;
16146 w->hscroll = hscroll;
16147 hscrolled_p = true;
16148 }
16149 }
16150 }
16151
16152 window = w->next;
16153 }
16154
16155
16156 return hscrolled_p;
16157 }
16158
16159
16160
16161
16162
16163
16164
16165
16166 static bool
16167 hscroll_windows (Lisp_Object window)
16168 {
16169 bool hscrolled_p = hscroll_window_tree (window);
16170 if (hscrolled_p)
16171 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16172 return hscrolled_p;
16173 }
16174
16175
16176
16177
16178
16179
16180
16181
16182
16183
16184 #ifdef GLYPH_DEBUG
16185
16186
16187
16188 static int debug_first_unchanged_at_end_vpos;
16189 static int debug_last_unchanged_at_beg_vpos;
16190
16191
16192
16193 static int debug_dvpos, debug_dy;
16194
16195
16196
16197 static ptrdiff_t debug_delta, debug_delta_bytes;
16198
16199
16200
16201
16202 static ptrdiff_t debug_end_vpos;
16203
16204
16205
16206
16207
16208 static void debug_method_add (struct window *, char const *, ...)
16209 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16210
16211 static void
16212 debug_method_add (struct window *w, char const *fmt, ...)
16213 {
16214 void *ptr = w;
16215 char *method = w->desired_matrix->method;
16216 int len = strlen (method);
16217 int size = sizeof w->desired_matrix->method;
16218 int remaining = size - len - 1;
16219 va_list ap;
16220
16221 if (len && remaining)
16222 {
16223 method[len] = '|';
16224 --remaining, ++len;
16225 }
16226
16227 va_start (ap, fmt);
16228 vsnprintf (method + len, remaining + 1, fmt, ap);
16229 va_end (ap);
16230
16231 if (trace_redisplay_p)
16232 fprintf (stderr, "%p (%s): %s\n",
16233 ptr,
16234 ((BUFFERP (w->contents)
16235 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16236 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16237 : "no buffer"),
16238 method + len);
16239 }
16240
16241 #endif
16242
16243
16244
16245
16246
16247
16248
16249 static bool
16250 text_outside_line_unchanged_p (struct window *w,
16251 ptrdiff_t start, ptrdiff_t end)
16252 {
16253 bool unchanged_p = true;
16254
16255
16256 if (window_outdated (w))
16257 {
16258
16259 if (GPT < start || Z - GPT < end)
16260 unchanged_p = false;
16261
16262
16263 if (unchanged_p
16264 && (BEG_UNCHANGED < start - 1
16265 || END_UNCHANGED < end))
16266 unchanged_p = false;
16267
16268
16269
16270 if (unchanged_p
16271 && FIXNUMP (BVAR (current_buffer, selective_display))
16272 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16273 && (BEG_UNCHANGED < start || GPT <= start))
16274 unchanged_p = false;
16275
16276
16277
16278
16279
16280
16281
16282
16283 if (unchanged_p)
16284 {
16285 if (BEG + BEG_UNCHANGED == start
16286 && overlay_touches_p (start))
16287 unchanged_p = false;
16288 if (END_UNCHANGED == end
16289 && overlay_touches_p (Z - end))
16290 unchanged_p = false;
16291 }
16292
16293
16294
16295
16296
16297
16298
16299
16300 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16301 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16302 unchanged_p = false;
16303 }
16304
16305 return unchanged_p;
16306 }
16307
16308
16309
16310
16311
16312
16313
16314
16315
16316 void
16317 redisplay (void)
16318 {
16319 redisplay_internal ();
16320 }
16321
16322
16323 static Lisp_Object
16324 overlay_arrow_string_or_property (Lisp_Object var)
16325 {
16326 Lisp_Object val;
16327
16328 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16329 return val;
16330
16331 return Voverlay_arrow_string;
16332 }
16333
16334
16335 static bool
16336 overlay_arrow_in_current_buffer_p (void)
16337 {
16338 Lisp_Object vlist;
16339
16340 for (vlist = Voverlay_arrow_variable_list;
16341 CONSP (vlist);
16342 vlist = XCDR (vlist))
16343 {
16344 Lisp_Object var = XCAR (vlist);
16345 Lisp_Object val;
16346
16347 if (!SYMBOLP (var))
16348 continue;
16349 val = find_symbol_value (var);
16350 if (MARKERP (val)
16351 && current_buffer == XMARKER (val)->buffer)
16352 return true;
16353 }
16354 return false;
16355 }
16356
16357
16358
16359
16360
16361
16362
16363 static bool
16364 overlay_arrows_changed_p (bool set_redisplay)
16365 {
16366 Lisp_Object vlist;
16367 bool changed = false;
16368
16369 for (vlist = Voverlay_arrow_variable_list;
16370 CONSP (vlist);
16371 vlist = XCDR (vlist))
16372 {
16373 Lisp_Object var = XCAR (vlist);
16374 Lisp_Object val, pstr;
16375
16376 if (!SYMBOLP (var))
16377 continue;
16378 val = find_symbol_value (var);
16379 if (!MARKERP (val))
16380 continue;
16381 if (! EQ (Fmarker_position (val),
16382
16383
16384 Fget (var, Qlast_arrow_position))
16385 || ! (pstr = overlay_arrow_string_or_property (var),
16386 EQ (pstr, Fget (var, Qlast_arrow_string))))
16387 {
16388 struct buffer *buf = XMARKER (val)->buffer;
16389
16390 if (set_redisplay)
16391 {
16392 if (buf)
16393 bset_redisplay (buf);
16394 changed = true;
16395 }
16396 else
16397 return true;
16398 }
16399 }
16400 return changed;
16401 }
16402
16403
16404
16405 static void
16406 update_overlay_arrows (int up_to_date)
16407 {
16408 Lisp_Object vlist;
16409
16410 for (vlist = Voverlay_arrow_variable_list;
16411 CONSP (vlist);
16412 vlist = XCDR (vlist))
16413 {
16414 Lisp_Object var = XCAR (vlist);
16415
16416 if (!SYMBOLP (var))
16417 continue;
16418
16419 if (up_to_date > 0)
16420 {
16421 Lisp_Object val = find_symbol_value (var);
16422 if (!MARKERP (val))
16423 continue;
16424 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16425 Fput (var, Qlast_arrow_string,
16426 overlay_arrow_string_or_property (var));
16427 }
16428 else if (up_to_date < 0
16429 || !NILP (Fget (var, Qlast_arrow_position)))
16430 {
16431 Fput (var, Qlast_arrow_position, Qt);
16432 Fput (var, Qlast_arrow_string, Qt);
16433 }
16434 }
16435 }
16436
16437
16438
16439
16440
16441
16442 static Lisp_Object
16443 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16444 {
16445 Lisp_Object vlist;
16446
16447 for (vlist = Voverlay_arrow_variable_list;
16448 CONSP (vlist);
16449 vlist = XCDR (vlist))
16450 {
16451 Lisp_Object var = XCAR (vlist);
16452 Lisp_Object val;
16453
16454 if (!SYMBOLP (var))
16455 continue;
16456
16457 val = find_symbol_value (var);
16458
16459 if (MARKERP (val)
16460 && current_buffer == XMARKER (val)->buffer
16461 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16462 {
16463 if (FRAME_WINDOW_P (it->f)
16464
16465
16466 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16467 {
16468 #ifdef HAVE_WINDOW_SYSTEM
16469 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16470 {
16471 int fringe_bitmap = lookup_fringe_bitmap (val);
16472 if (fringe_bitmap != 0)
16473 return make_fixnum (fringe_bitmap);
16474 }
16475 #endif
16476 return make_fixnum (-1);
16477 }
16478 return overlay_arrow_string_or_property (var);
16479 }
16480 }
16481
16482 return Qnil;
16483 }
16484
16485
16486
16487
16488
16489 static bool
16490 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16491 struct buffer *buf, ptrdiff_t pt)
16492 {
16493 ptrdiff_t start, end;
16494 Lisp_Object prop;
16495 Lisp_Object buffer;
16496
16497 XSETBUFFER (buffer, buf);
16498
16499
16500 if (prev_buf == buf)
16501 {
16502 if (prev_pt == pt)
16503
16504 return false;
16505
16506 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16507 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16508 && composition_valid_p (start, end, prop)
16509 && start < prev_pt && end > prev_pt)
16510
16511
16512 return (pt <= start || pt >= end);
16513 }
16514
16515
16516 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16517 && find_composition (pt, -1, &start, &end, &prop, buffer)
16518 && composition_valid_p (start, end, prop)
16519 && start < pt && end > pt);
16520 }
16521
16522
16523
16524 static void
16525 reconsider_clip_changes (struct window *w)
16526 {
16527 struct buffer *b = XBUFFER (w->contents);
16528
16529 if (b->clip_changed
16530 && w->window_end_valid
16531 && w->current_matrix->buffer == b
16532 && w->current_matrix->zv == BUF_ZV (b)
16533 && w->current_matrix->begv == BUF_BEGV (b))
16534 b->clip_changed = false;
16535
16536
16537
16538
16539
16540 if (!b->clip_changed && w->window_end_valid)
16541 {
16542 ptrdiff_t pt = (w == XWINDOW (selected_window)
16543 ? PT : marker_position (w->pointm));
16544
16545 if ((w->current_matrix->buffer != b || pt != w->last_point)
16546 && check_point_in_composition (w->current_matrix->buffer,
16547 w->last_point, b, pt))
16548 b->clip_changed = true;
16549 }
16550 }
16551
16552 static void
16553 propagate_buffer_redisplay (void)
16554 {
16555
16556
16557
16558
16559
16560
16561
16562
16563
16564 Lisp_Object ws = window_list ();
16565 for (; CONSP (ws); ws = XCDR (ws))
16566 {
16567 struct window *thisw = XWINDOW (XCAR (ws));
16568 struct buffer *thisb = XBUFFER (thisw->contents);
16569 if (thisb->text->redisplay)
16570 thisw->redisplay = true;
16571 }
16572 }
16573
16574 #define STOP_POLLING \
16575 do { if (! polling_stopped_here) stop_polling (); \
16576 polling_stopped_here = true; } while (false)
16577
16578 #define RESUME_POLLING \
16579 do { if (polling_stopped_here) start_polling (); \
16580 polling_stopped_here = false; } while (false)
16581
16582
16583
16584
16585 static void
16586 redisplay_internal (void)
16587 {
16588 struct window *w = XWINDOW (selected_window);
16589 struct window *sw;
16590 struct frame *fr;
16591 bool pending;
16592 bool must_finish = false, match_p;
16593 struct text_pos tlbufpos, tlendpos;
16594 int number_of_visible_frames;
16595 struct frame *sf;
16596 bool polling_stopped_here = false;
16597 Lisp_Object tail, frame;
16598
16599
16600
16601
16602 enum { MAX_HSCROLL_RETRIES = 16 };
16603 int hscroll_retries = 0;
16604
16605
16606
16607
16608
16609
16610 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16611 int garbaged_frame_retries = 0;
16612
16613
16614
16615 bool consider_all_windows_p;
16616
16617
16618 bool update_miniwindow_p = false;
16619
16620 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16621
16622
16623
16624
16625 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16626 && redisplay_skip_initial_frame)
16627 || !NILP (Vinhibit_redisplay))
16628 return;
16629
16630
16631
16632
16633 fr = XFRAME (w->frame);
16634 sf = SELECTED_FRAME ();
16635
16636 if (!fr->glyphs_initialized_p)
16637 return;
16638
16639 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16640 if (popup_activated ())
16641 return;
16642 #endif
16643
16644 #if defined (HAVE_HAIKU)
16645 if (popup_activated_p)
16646 return;
16647 #endif
16648
16649
16650 if (redisplaying_p)
16651 return;
16652
16653
16654
16655 specpdl_ref count = SPECPDL_INDEX ();
16656 record_unwind_protect_void (unwind_redisplay);
16657 redisplaying_p = true;
16658 block_buffer_flips ();
16659 specbind (Qinhibit_free_realized_faces, Qnil);
16660
16661
16662 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16663
16664 FOR_EACH_FRAME (tail, frame)
16665 XFRAME (frame)->already_hscrolled_p = false;
16666
16667 reset_outermost_restrictions ();
16668
16669 retry:
16670
16671 sw = w;
16672
16673 pending = false;
16674 forget_escape_and_glyphless_faces ();
16675
16676 inhibit_free_realized_faces = false;
16677
16678
16679
16680
16681 if (face_change)
16682 windows_or_buffers_changed = 47;
16683
16684 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16685 && FRAME_TTY (sf)->previous_frame != sf)
16686 {
16687
16688
16689
16690 SET_FRAME_GARBAGED (sf);
16691 #if !defined DOS_NT && !defined HAVE_ANDROID
16692 set_tty_color_mode (FRAME_TTY (sf), sf);
16693 #endif
16694 FRAME_TTY (sf)->previous_frame = sf;
16695 }
16696
16697
16698
16699
16700 number_of_visible_frames = 0;
16701
16702 FOR_EACH_FRAME (tail, frame)
16703 {
16704 struct frame *f = XFRAME (frame);
16705
16706 if (FRAME_REDISPLAY_P (f))
16707 {
16708 ++number_of_visible_frames;
16709
16710 if (f->fonts_changed)
16711 {
16712 adjust_frame_glyphs (f);
16713
16714
16715
16716
16717
16718
16719 SET_FRAME_GARBAGED (f);
16720 f->fonts_changed = false;
16721 }
16722
16723
16724 if (f != sf && f->cursor_type_changed)
16725 fset_redisplay (f);
16726 }
16727 clear_desired_matrices (f);
16728 }
16729
16730
16731 do_pending_window_change (true);
16732
16733
16734 clear_garbaged_frames ();
16735
16736
16737 if (NILP (Vmemory_full))
16738 prepare_menu_bars ();
16739
16740
16741
16742
16743
16744 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16745 sw = w;
16746
16747 reconsider_clip_changes (w);
16748
16749
16750 match_p = XBUFFER (w->contents) == current_buffer;
16751 if (match_p)
16752 {
16753
16754 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16755 w->update_mode_line = true;
16756
16757 if (mode_line_update_needed (w))
16758 w->update_mode_line = true;
16759
16760
16761
16762
16763 if (current_buffer->clip_changed)
16764 bset_update_mode_line (current_buffer);
16765 }
16766
16767
16768
16769
16770
16771
16772 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16773 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16774 || (message_cleared_p
16775 && minibuf_level == 0
16776
16777
16778 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16779 {
16780 echo_area_display (false);
16781
16782 if (message_cleared_p)
16783 update_miniwindow_p = true;
16784
16785 must_finish = true;
16786
16787
16788
16789
16790
16791 if (!display_last_displayed_message_p)
16792 message_cleared_p = false;
16793 }
16794 else if (EQ (selected_window, minibuf_window)
16795 && (current_buffer->clip_changed || window_outdated (w))
16796 && resize_mini_window (w, false))
16797 {
16798
16799
16800 must_finish = true;
16801
16802
16803
16804
16805 clear_garbaged_frames ();
16806 }
16807
16808 if (!NILP (Vrun_hooks))
16809 run_window_change_functions ();
16810
16811 if (windows_or_buffers_changed && !update_mode_lines)
16812
16813
16814
16815 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16816 ? REDISPLAY_SOME : 32);
16817
16818
16819
16820
16821
16822 overlay_arrows_changed_p (true);
16823
16824 consider_all_windows_p = (update_mode_lines
16825 || windows_or_buffers_changed);
16826
16827 #define AINC(a,i) \
16828 { \
16829 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16830 if (FIXNUMP (entry)) \
16831 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16832 }
16833
16834 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16835 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16836
16837
16838
16839
16840
16841 tlbufpos = this_line_start_pos;
16842 tlendpos = this_line_end_pos;
16843 if (!consider_all_windows_p
16844 && CHARPOS (tlbufpos) > 0
16845 && !w->update_mode_line
16846 && !current_buffer->clip_changed
16847 && !current_buffer->prevent_redisplay_optimizations_p
16848 && FRAME_REDISPLAY_P (XFRAME (w->frame))
16849 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16850 && !XFRAME (w->frame)->cursor_type_changed
16851 && !XFRAME (w->frame)->face_change
16852
16853 && this_line_buffer == current_buffer
16854 && match_p
16855 && !w->force_start
16856 && !w->optional_new_start
16857
16858 && PT >= CHARPOS (tlbufpos)
16859 && PT <= Z - CHARPOS (tlendpos)
16860
16861
16862
16863
16864
16865
16866 && (NILP (Vdisplay_line_numbers)
16867 || EQ (Vdisplay_line_numbers, Qvisual))
16868
16869
16870 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16871 CHARPOS (tlendpos)))
16872 {
16873 if (CHARPOS (tlbufpos) > BEGV
16874 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16875 && (CHARPOS (tlbufpos) == ZV
16876 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16877
16878 goto cancel;
16879 else if (window_outdated (w) || MINI_WINDOW_P (w))
16880 {
16881
16882
16883
16884
16885
16886
16887
16888
16889
16890
16891
16892
16893
16894
16895
16896 struct it it;
16897 int line_height_before = this_line_pixel_height;
16898
16899
16900
16901 start_display (&it, w, tlbufpos);
16902
16903
16904 if (it.current_x != this_line_start_x)
16905 goto cancel;
16906
16907
16908
16909
16910 if (it.sp > 1
16911 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16912 goto cancel;
16913 redisplay_trace ("trying display optimization 1\n");
16914 w->cursor.vpos = -1;
16915 overlay_arrow_seen = false;
16916 it.vpos = this_line_vpos;
16917 it.current_y = this_line_y;
16918 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16919 display_line (&it, -1);
16920
16921
16922
16923 if (w->cursor.vpos >= 0
16924
16925
16926 && CHARPOS (this_line_start_pos)
16927
16928 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16929
16930
16931 && this_line_pixel_height == line_height_before
16932
16933
16934
16935
16936 && !hscrolling_current_line_p (w))
16937 {
16938
16939
16940 if (it.current_y < it.last_visible_y)
16941 {
16942 struct glyph_row *row
16943 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16944 ptrdiff_t delta, delta_bytes;
16945
16946
16947
16948
16949
16950
16951 delta = (Z
16952 - CHARPOS (tlendpos)
16953 - MATRIX_ROW_START_CHARPOS (row));
16954 delta_bytes = (Z_BYTE
16955 - BYTEPOS (tlendpos)
16956 - MATRIX_ROW_START_BYTEPOS (row));
16957
16958 increment_matrix_positions (w->current_matrix,
16959 this_line_vpos + 1,
16960 w->current_matrix->nrows,
16961 delta, delta_bytes);
16962 }
16963
16964
16965
16966
16967 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16968 {
16969 if (w->window_end_vpos < this_line_vpos)
16970 w->window_end_vpos = this_line_vpos;
16971 }
16972 else if (w->window_end_vpos == this_line_vpos
16973 && this_line_vpos > 0)
16974 w->window_end_vpos = this_line_vpos - 1;
16975 w->window_end_valid = false;
16976
16977
16978 w->desired_matrix->no_scrolling_p = true;
16979
16980 #ifdef GLYPH_DEBUG
16981 *w->desired_matrix->method = 0;
16982 debug_method_add (w, "optimization 1");
16983 #endif
16984 #ifdef HAVE_WINDOW_SYSTEM
16985 update_window_fringes (w, false);
16986 #endif
16987 goto update;
16988 }
16989 else
16990 goto cancel;
16991 }
16992 else if (
16993 PT == w->last_point
16994
16995
16996
16997
16998 && 0 <= w->cursor.vpos
16999 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
17000 {
17001 if (!must_finish)
17002 {
17003 do_pending_window_change (true);
17004
17005 if (WINDOWP (selected_window)
17006 && (w = XWINDOW (selected_window)) != sw)
17007 goto retry;
17008
17009
17010
17011 if (w->cursor_off_p == w->last_cursor_off_p)
17012 goto end_of_redisplay;
17013 }
17014 goto update;
17015 }
17016
17017
17018 else if (NILP (Vshow_trailing_whitespace)
17019 && !cursor_in_echo_area
17020 && !composition_break_at_point)
17021 {
17022 struct it it;
17023 struct glyph_row *row;
17024
17025
17026
17027
17028 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
17029 NULL, DEFAULT_FACE_ID);
17030 it.current_x = this_line_start_x;
17031 it.current_y = this_line_y;
17032 it.vpos = this_line_vpos;
17033
17034 if (current_buffer->long_line_optimizations_p
17035 && it.line_wrap == TRUNCATE
17036 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
17037 {
17038
17039
17040
17041 reseat_at_next_visible_line_start (&it, false);
17042 if (IT_CHARPOS (it) <= PT)
17043 it.vpos = this_line_vpos + 1;
17044 }
17045 else
17046 {
17047
17048
17049 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
17050 }
17051
17052 if (it.vpos == this_line_vpos
17053 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
17054 row->enabled_p))
17055 {
17056 eassert (this_line_vpos == it.vpos);
17057 eassert (this_line_y == it.current_y);
17058 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
17059 if (cursor_row_fully_visible_p (w, false, true, false))
17060 {
17061 #ifdef GLYPH_DEBUG
17062 *w->desired_matrix->method = 0;
17063 debug_method_add (w, "optimization 3");
17064 #endif
17065 goto update;
17066 }
17067 else
17068 goto cancel;
17069 }
17070 else
17071 goto cancel;
17072 }
17073
17074 cancel:
17075
17076 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
17077 }
17078
17079 CHARPOS (this_line_start_pos) = 0;
17080 ++clear_face_cache_count;
17081 #ifdef HAVE_WINDOW_SYSTEM
17082 ++clear_image_cache_count;
17083 #endif
17084
17085
17086
17087
17088
17089
17090 if (consider_all_windows_p)
17091 {
17092 FOR_EACH_FRAME (tail, frame)
17093 XFRAME (frame)->updated_p = false;
17094
17095 propagate_buffer_redisplay ();
17096
17097 FOR_EACH_FRAME (tail, frame)
17098 {
17099 struct frame *f = XFRAME (frame);
17100
17101
17102
17103 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
17104 && !EQ (FRAME_TTY (f)->top_frame, frame))
17105 continue;
17106
17107 retry_frame:
17108 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
17109 {
17110 bool gcscrollbars
17111
17112 = f->redisplay || !REDISPLAY_SOME_P ();
17113 bool f_redisplay_flag = f->redisplay;
17114
17115
17116
17117
17118 if (!FRAME_LIVE_P (f))
17119 continue;
17120
17121
17122
17123 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
17124 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
17125
17126 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17127 {
17128
17129
17130
17131
17132
17133
17134
17135 f->inhibit_clear_image_cache = true;
17136 redisplay_windows (FRAME_ROOT_WINDOW (f));
17137 }
17138
17139
17140 else if (!REDISPLAY_SOME_P ())
17141 f->redisplay = true;
17142
17143
17144 if (!FRAME_LIVE_P (f))
17145 continue;
17146
17147
17148
17149 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17150 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17151
17152 if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
17153 {
17154
17155 if (f->fonts_changed)
17156 {
17157 adjust_frame_glyphs (f);
17158
17159
17160
17161 SET_FRAME_GARBAGED (f);
17162 f->fonts_changed = false;
17163 goto retry_frame;
17164 }
17165
17166
17167 if (!f->already_hscrolled_p)
17168 {
17169 f->already_hscrolled_p = true;
17170 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17171 && hscroll_windows (f->root_window))
17172 {
17173 hscroll_retries++;
17174 goto retry_frame;
17175 }
17176 }
17177
17178
17179
17180
17181
17182
17183
17184
17185
17186
17187
17188
17189 if (!f_redisplay_flag && f->redisplay)
17190 goto retry_frame;
17191
17192
17193
17194
17195
17196
17197
17198
17199
17200 if (FRAME_GARBAGED_P (f)
17201 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17202 goto retry;
17203
17204 #ifdef HAVE_WINDOW_SYSTEM
17205 if (FRAME_WINDOW_P (f)
17206 && FRAME_RIF (f)->clear_under_internal_border)
17207 FRAME_RIF (f)->clear_under_internal_border (f);
17208 #endif
17209
17210
17211
17212 if (interrupt_input)
17213 unrequest_sigio ();
17214 STOP_POLLING;
17215
17216 pending |= update_frame (f, false, false);
17217
17218
17219
17220
17221
17222
17223
17224 if (FRAME_GARBAGED_P (f))
17225 {
17226 fset_redisplay (f);
17227 f->garbaged = false;
17228 goto retry_frame;
17229 }
17230 f->cursor_type_changed = false;
17231 f->updated_p = true;
17232 f->inhibit_clear_image_cache = false;
17233 }
17234 }
17235 }
17236
17237 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17238
17239 if (!pending)
17240 {
17241
17242
17243
17244 FOR_EACH_FRAME (tail, frame)
17245 {
17246 struct frame *f = XFRAME (frame);
17247 if (f->updated_p)
17248 {
17249 f->redisplay = false;
17250 f->garbaged = false;
17251 mark_window_display_accurate (f->root_window, true);
17252 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17253 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17254 }
17255 }
17256 }
17257 }
17258 else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17259 {
17260 sf->inhibit_clear_image_cache = true;
17261 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17262
17263
17264 internal_condition_case_1 (redisplay_window_1, selected_window,
17265 list_of_error,
17266 redisplay_window_error);
17267 if (update_miniwindow_p)
17268 {
17269 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17270
17271 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17272 internal_condition_case_1 (redisplay_window_1, mini_window,
17273 list_of_error,
17274 redisplay_window_error);
17275 }
17276
17277
17278
17279 update:
17280
17281
17282
17283 if (sf->fonts_changed || sf->redisplay)
17284 {
17285 if (sf->redisplay)
17286 {
17287
17288
17289
17290
17291
17292
17293 windows_or_buffers_changed = 50;
17294 }
17295 goto retry;
17296 }
17297
17298
17299
17300 inhibit_free_realized_faces = true;
17301
17302
17303
17304
17305 if (interrupt_input)
17306 unrequest_sigio ();
17307 STOP_POLLING;
17308
17309 if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
17310 {
17311 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17312 && hscroll_windows (selected_window))
17313 {
17314 hscroll_retries++;
17315 goto retry;
17316 }
17317
17318 XWINDOW (selected_window)->must_be_updated_p = true;
17319 pending = update_frame (sf, false, false);
17320 sf->cursor_type_changed = false;
17321 sf->inhibit_clear_image_cache = false;
17322 }
17323
17324
17325
17326
17327
17328
17329 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17330 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17331
17332 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17333 {
17334 XWINDOW (mini_window)->must_be_updated_p = true;
17335 pending |= update_frame (mini_frame, false, false);
17336 mini_frame->cursor_type_changed = false;
17337 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17338 && hscroll_windows (mini_window))
17339 {
17340 hscroll_retries++;
17341 goto retry;
17342 }
17343 }
17344 }
17345
17346
17347
17348 if (pending)
17349 {
17350
17351
17352
17353 CHARPOS (this_line_start_pos) = 0;
17354
17355
17356 update_overlay_arrows (0);
17357
17358
17359
17360 if (!WINDOW_FULL_WIDTH_P (w)
17361 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17362 update_mode_lines = 36;
17363 }
17364 else
17365 {
17366 if (!consider_all_windows_p)
17367 {
17368
17369
17370 if (XBUFFER (w->contents)->text->redisplay
17371 && buffer_window_count (XBUFFER (w->contents)) > 1)
17372
17373
17374 propagate_buffer_redisplay ();
17375 mark_window_display_accurate_1 (w, true);
17376
17377
17378 update_overlay_arrows (1);
17379
17380 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17381 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17382 }
17383
17384 update_mode_lines = 0;
17385 windows_or_buffers_changed = 0;
17386 }
17387
17388
17389
17390
17391
17392 if (interrupt_input)
17393 request_sigio ();
17394 RESUME_POLLING;
17395
17396
17397
17398
17399
17400
17401
17402 if (!pending)
17403 {
17404 int new_count = 0;
17405
17406 FOR_EACH_FRAME (tail, frame)
17407 {
17408 if (FRAME_REDISPLAY_P (XFRAME (frame)))
17409 new_count++;
17410 }
17411
17412 if (new_count != number_of_visible_frames)
17413 windows_or_buffers_changed = 52;
17414 }
17415
17416
17417 do_pending_window_change (true);
17418
17419
17420
17421 if ((windows_or_buffers_changed && !pending)
17422 || (WINDOWP (selected_window)
17423 && (w = XWINDOW (selected_window)) != sw))
17424 goto retry;
17425
17426
17427
17428
17429
17430
17431
17432 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17433 {
17434 clear_face_cache (false);
17435 clear_face_cache_count = 0;
17436 }
17437
17438 #ifdef HAVE_WINDOW_SYSTEM
17439 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17440 {
17441 clear_image_caches (Qnil);
17442 clear_image_cache_count = 0;
17443 }
17444 #endif
17445
17446 end_of_redisplay:
17447 #ifdef HAVE_NS
17448 ns_set_doc_edited ();
17449 #endif
17450 if (interrupt_input && interrupts_deferred)
17451 request_sigio ();
17452
17453
17454
17455 if (max_redisplay_ticks > 0)
17456 update_redisplay_ticks (0, NULL);
17457
17458 unbind_to (count, Qnil);
17459 RESUME_POLLING;
17460 }
17461
17462 static void
17463 unwind_redisplay_preserve_echo_area (void)
17464 {
17465 unblock_buffer_flips ();
17466 }
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479 void
17480 redisplay_preserve_echo_area (int from_where)
17481 {
17482 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17483
17484 block_input ();
17485 specpdl_ref count = SPECPDL_INDEX ();
17486 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17487 block_buffer_flips ();
17488 unblock_input ();
17489
17490 if (!NILP (echo_area_buffer[1]))
17491 {
17492
17493
17494 display_last_displayed_message_p = true;
17495 redisplay_internal ();
17496 display_last_displayed_message_p = false;
17497 }
17498 else
17499 redisplay_internal ();
17500
17501 flush_frame (SELECTED_FRAME ());
17502 unbind_to (count, Qnil);
17503 }
17504
17505
17506
17507
17508 static void
17509 unwind_redisplay (void)
17510 {
17511 redisplaying_p = false;
17512 unblock_buffer_flips ();
17513 }
17514
17515
17516
17517 void
17518 unwind_display_working_on_window (void)
17519 {
17520 display_working_on_window_p = false;
17521 }
17522
17523
17524
17525
17526
17527
17528 static void
17529 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17530 {
17531 struct buffer *b = XBUFFER (w->contents);
17532 #ifdef HAVE_TEXT_CONVERSION
17533 ptrdiff_t prev_point, prev_mark;
17534 #endif
17535
17536 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17537 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17538 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17539
17540 if (accurate_p)
17541 {
17542 b->clip_changed = false;
17543 b->prevent_redisplay_optimizations_p = false;
17544 eassert (buffer_window_count (b) > 0);
17545
17546
17547
17548 b->text->redisplay = false;
17549
17550 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17551 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17552 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17553 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17554
17555 w->current_matrix->buffer = b;
17556 w->current_matrix->begv = BUF_BEGV (b);
17557 w->current_matrix->zv = BUF_ZV (b);
17558 w->current_matrix->header_line_p = window_wants_header_line (w);
17559 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17560
17561 w->last_cursor_vpos = w->cursor.vpos;
17562 w->last_cursor_off_p = w->cursor_off_p;
17563
17564 #ifdef HAVE_TEXT_CONVERSION
17565 prev_point = w->last_point;
17566 prev_mark = w->last_mark;
17567 #endif
17568
17569 if (w == XWINDOW (selected_window))
17570 w->last_point = BUF_PT (b);
17571 else
17572 w->last_point = marker_position (w->pointm);
17573
17574
17575
17576
17577
17578 if (XMARKER (BVAR (b, mark))->buffer == b
17579 && !NILP (BVAR (b, mark_active)))
17580 w->last_mark = marker_position (BVAR (b, mark));
17581 else
17582 w->last_mark = -1;
17583
17584 #ifdef HAVE_TEXT_CONVERSION
17585
17586 w->ephemeral_last_point = w->last_point;
17587
17588
17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602 if ((prev_point != w->last_point
17603 || prev_mark != w->last_mark)
17604 && FRAME_WINDOW_P (WINDOW_XFRAME (w))
17605 && w == XWINDOW (WINDOW_XFRAME (w)->selected_window))
17606 report_point_change (WINDOW_XFRAME (w), w, b);
17607 #endif
17608
17609 w->window_end_valid = true;
17610 w->update_mode_line = false;
17611 w->preserve_vscroll_p = false;
17612 }
17613
17614 w->redisplay = !accurate_p;
17615 }
17616
17617
17618
17619
17620
17621
17622
17623 void
17624 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17625 {
17626 struct window *w;
17627
17628 for (; !NILP (window); window = w->next)
17629 {
17630 w = XWINDOW (window);
17631 if (WINDOWP (w->contents))
17632 mark_window_display_accurate (w->contents, accurate_p);
17633 else
17634 mark_window_display_accurate_1 (w, accurate_p);
17635 }
17636
17637 if (accurate_p)
17638 update_overlay_arrows (1);
17639 else
17640
17641
17642
17643 update_overlay_arrows (-1);
17644 }
17645
17646
17647
17648
17649
17650
17651
17652 Lisp_Object
17653 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17654 {
17655 Lisp_Object val;
17656
17657 if (ASCII_CHAR_P (c))
17658 {
17659 val = dp->ascii;
17660 if (SUB_CHAR_TABLE_P (val))
17661 val = XSUB_CHAR_TABLE (val)->contents[c];
17662 }
17663 else
17664 {
17665 Lisp_Object table;
17666
17667 XSETCHAR_TABLE (table, dp);
17668 val = char_table_ref (table, c);
17669 }
17670 if (NILP (val))
17671 val = dp->defalt;
17672 return val;
17673 }
17674
17675 static int buffer_flip_blocked_depth;
17676
17677 static void
17678 block_buffer_flips (void)
17679 {
17680 eassert (buffer_flip_blocked_depth >= 0);
17681 buffer_flip_blocked_depth++;
17682 }
17683
17684 static void
17685 unblock_buffer_flips (void)
17686 {
17687 eassert (buffer_flip_blocked_depth > 0);
17688 if (--buffer_flip_blocked_depth == 0)
17689 {
17690 Lisp_Object tail, frame;
17691 block_input ();
17692 FOR_EACH_FRAME (tail, frame)
17693 {
17694 struct frame *f = XFRAME (frame);
17695 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17696 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17697 }
17698 unblock_input ();
17699 }
17700 }
17701
17702 bool
17703 buffer_flipping_blocked_p (void)
17704 {
17705 return buffer_flip_blocked_depth > 0;
17706 }
17707
17708
17709
17710
17711
17712
17713
17714
17715 static void
17716 redisplay_windows (Lisp_Object window)
17717 {
17718 while (!NILP (window))
17719 {
17720 struct window *w = XWINDOW (window);
17721
17722 if (WINDOWP (w->contents))
17723 redisplay_windows (w->contents);
17724 else if (BUFFERP (w->contents))
17725 {
17726 displayed_buffer = XBUFFER (w->contents);
17727
17728
17729 internal_condition_case_1 (redisplay_window_0, window,
17730 list_of_error,
17731 redisplay_window_error);
17732 }
17733
17734 window = w->next;
17735 }
17736 }
17737
17738 static Lisp_Object
17739 redisplay_window_error (Lisp_Object error_data)
17740 {
17741 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17742
17743
17744
17745 if (max_redisplay_ticks > 0
17746 && CONSP (error_data)
17747 && EQ (XCAR (error_data), Qerror)
17748 && STRINGP (XCAR (XCDR (error_data))))
17749 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17750 XCAR (XCDR (error_data))),
17751 Vdelayed_warnings_list);
17752 return Qnil;
17753 }
17754
17755 static Lisp_Object
17756 redisplay_window_0 (Lisp_Object window)
17757 {
17758 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17759 redisplay_window (window, false);
17760 return Qnil;
17761 }
17762
17763 static Lisp_Object
17764 redisplay_window_1 (Lisp_Object window)
17765 {
17766 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17767 redisplay_window (window, true);
17768 return Qnil;
17769 }
17770
17771
17772
17773
17774
17775
17776
17777
17778
17779
17780
17781
17782
17783
17784
17785
17786
17787
17788
17789 void
17790 update_redisplay_ticks (int ticks, struct window *w)
17791 {
17792
17793 static struct window *cwindow;
17794 static EMACS_INT window_ticks;
17795
17796
17797
17798
17799 if (!ticks && w != cwindow)
17800 {
17801 cwindow = w;
17802 window_ticks = 0;
17803 }
17804
17805
17806 if ((!w && !redisplaying_p && !display_working_on_window_p)
17807
17808
17809 || (w && MINI_WINDOW_P (w)))
17810 return;
17811
17812 if (ticks > 0)
17813 window_ticks += ticks;
17814 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17815 {
17816
17817
17818
17819 Lisp_Object contents = w ? w->contents : Qnil;
17820 char *bufname =
17821 NILP (contents)
17822 ? SSDATA (BVAR (current_buffer, name))
17823 : (BUFFERP (contents)
17824 ? SSDATA (BVAR (XBUFFER (contents), name))
17825 : (char *) "<unknown>");
17826
17827 windows_or_buffers_changed = 177;
17828
17829
17830
17831 if (w && w->desired_matrix)
17832 w->desired_matrix->no_scrolling_p = true;
17833 error ("Window showing buffer %s takes too long to redisplay", bufname);
17834 }
17835 }
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846 static bool
17847 set_cursor_from_row (struct window *w, struct glyph_row *row,
17848 struct glyph_matrix *matrix,
17849 ptrdiff_t delta, ptrdiff_t delta_bytes,
17850 int dy, int dvpos)
17851 {
17852 struct glyph *glyph = row->glyphs[TEXT_AREA];
17853 struct glyph *end = glyph + row->used[TEXT_AREA];
17854 struct glyph *cursor = NULL;
17855
17856 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17857 int x = row->x;
17858 ptrdiff_t pt_old = PT - delta;
17859 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17860 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17861 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17862
17863
17864 struct glyph *glyphs_end = end;
17865
17866
17867 bool match_with_avoid_cursor = false;
17868
17869
17870 bool string_seen = false;
17871
17872
17873 ptrdiff_t bpos_max = pos_before;
17874 ptrdiff_t bpos_min = pos_after;
17875
17876
17877 ptrdiff_t bpos_covered = 0;
17878
17879
17880 bool string_from_text_prop = false;
17881
17882
17883
17884
17885 eassert (!row->mode_line_p);
17886 if (row->mode_line_p)
17887 return false;
17888
17889
17890
17891
17892 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17893 {
17894 if (!row->reversed_p)
17895 {
17896 while (glyph < end
17897 && NILP (glyph->object)
17898 && glyph->charpos < 0)
17899 {
17900 x += glyph->pixel_width;
17901 ++glyph;
17902 }
17903 while (end > glyph
17904 && NILP ((end - 1)->object)
17905
17906
17907 && (end - 1)->charpos <= 0)
17908 --end;
17909 glyph_before = glyph - 1;
17910 glyph_after = end;
17911 }
17912 else
17913 {
17914 struct glyph *g;
17915
17916
17917
17918 glyphs_end = end = glyph - 1;
17919 glyph += row->used[TEXT_AREA] - 1;
17920
17921 while (glyph > end + 1
17922 && NILP (glyph->object)
17923 && glyph->charpos < 0)
17924 --glyph;
17925 if (NILP (glyph->object) && glyph->charpos < 0)
17926 --glyph;
17927
17928
17929 for (x = 0, g = end + 1; g < glyph; g++)
17930 x += g->pixel_width;
17931 while (end < glyph
17932 && NILP ((end + 1)->object)
17933 && (end + 1)->charpos <= 0)
17934 ++end;
17935 glyph_before = glyph + 1;
17936 glyph_after = end;
17937 }
17938 }
17939 else if (row->reversed_p)
17940 {
17941
17942
17943
17944 cursor = end - 1;
17945
17946
17947
17948 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17949 && !WINDOW_RIGHTMOST_P (w)
17950 && cursor == row->glyphs[LAST_AREA] - 1)
17951 cursor--;
17952 x = -1;
17953 }
17954
17955
17956
17957
17958
17959 if (!row->reversed_p)
17960 while (
17961 glyph < end
17962
17963 && !NILP (glyph->object))
17964 {
17965 if (BUFFERP (glyph->object))
17966 {
17967 ptrdiff_t dpos = glyph->charpos - pt_old;
17968
17969 if (glyph->charpos > bpos_max)
17970 bpos_max = glyph->charpos;
17971 if (glyph->charpos < bpos_min)
17972 bpos_min = glyph->charpos;
17973 if (!glyph->avoid_cursor_p)
17974 {
17975
17976
17977 if (dpos == 0)
17978 {
17979 match_with_avoid_cursor = false;
17980 break;
17981 }
17982
17983
17984 if (0 > dpos && dpos > pos_before - pt_old)
17985 {
17986 pos_before = glyph->charpos;
17987 glyph_before = glyph;
17988 }
17989 else if (0 < dpos && dpos < pos_after - pt_old)
17990 {
17991 pos_after = glyph->charpos;
17992 glyph_after = glyph;
17993 }
17994 }
17995 else if (dpos == 0)
17996 match_with_avoid_cursor = true;
17997 }
17998 else if (STRINGP (glyph->object))
17999 {
18000 Lisp_Object chprop;
18001 ptrdiff_t glyph_pos = glyph->charpos;
18002
18003 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18004 glyph->object);
18005 if (!NILP (chprop))
18006 {
18007
18008
18009
18010
18011
18012
18013
18014
18015
18016
18017 ptrdiff_t prop_pos =
18018 string_buffer_position_lim (glyph->object, pos_before,
18019 pos_after, false);
18020
18021 if (prop_pos >= pos_before)
18022 bpos_max = prop_pos;
18023 }
18024 if (FIXNUMP (chprop))
18025 {
18026 bpos_covered = bpos_max + XFIXNUM (chprop);
18027
18028
18029
18030
18031
18032
18033
18034
18035
18036
18037
18038 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18039 {
18040 cursor = glyph;
18041 break;
18042 }
18043 }
18044
18045 string_seen = true;
18046 }
18047 x += glyph->pixel_width;
18048 ++glyph;
18049 }
18050 else if (glyph > end)
18051 while (!NILP (glyph->object))
18052 {
18053 if (BUFFERP (glyph->object))
18054 {
18055 ptrdiff_t dpos = glyph->charpos - pt_old;
18056
18057 if (glyph->charpos > bpos_max)
18058 bpos_max = glyph->charpos;
18059 if (glyph->charpos < bpos_min)
18060 bpos_min = glyph->charpos;
18061 if (!glyph->avoid_cursor_p)
18062 {
18063 if (dpos == 0)
18064 {
18065 match_with_avoid_cursor = false;
18066 break;
18067 }
18068 if (0 > dpos && dpos > pos_before - pt_old)
18069 {
18070 pos_before = glyph->charpos;
18071 glyph_before = glyph;
18072 }
18073 else if (0 < dpos && dpos < pos_after - pt_old)
18074 {
18075 pos_after = glyph->charpos;
18076 glyph_after = glyph;
18077 }
18078 }
18079 else if (dpos == 0)
18080 match_with_avoid_cursor = true;
18081 }
18082 else if (STRINGP (glyph->object))
18083 {
18084 Lisp_Object chprop;
18085 ptrdiff_t glyph_pos = glyph->charpos;
18086
18087 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
18088 glyph->object);
18089 if (!NILP (chprop))
18090 {
18091 ptrdiff_t prop_pos =
18092 string_buffer_position_lim (glyph->object, pos_before,
18093 pos_after, false);
18094
18095 if (prop_pos >= pos_before)
18096 bpos_max = prop_pos;
18097 }
18098 if (FIXNUMP (chprop))
18099 {
18100 bpos_covered = bpos_max + XFIXNUM (chprop);
18101
18102
18103
18104 if (bpos_max <= pt_old && bpos_covered >= pt_old)
18105 {
18106 cursor = glyph;
18107 break;
18108 }
18109 }
18110 string_seen = true;
18111 }
18112 --glyph;
18113 if (glyph == glyphs_end)
18114 {
18115 x--;
18116 break;
18117 }
18118 x -= glyph->pixel_width;
18119 }
18120
18121
18122
18123
18124 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18125 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
18126 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
18127 {
18128
18129
18130
18131
18132
18133 bool empty_line_p =
18134 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
18135 && NILP (glyph->object) && glyph->charpos > 0
18136
18137
18138
18139
18140 && !(row->continued_p || row->truncated_on_right_p));
18141
18142 if (row->ends_in_ellipsis_p && pos_after == last_pos)
18143 {
18144 ptrdiff_t ellipsis_pos;
18145
18146
18147 if (!row->reversed_p)
18148 {
18149 ellipsis_pos = (glyph - 1)->charpos;
18150 while (glyph > row->glyphs[TEXT_AREA]
18151 && (glyph - 1)->charpos == ellipsis_pos)
18152 glyph--, x -= glyph->pixel_width;
18153
18154
18155
18156 x += glyph->pixel_width;
18157 glyph++;
18158 }
18159 else
18160 {
18161 ellipsis_pos = (glyph + 1)->charpos;
18162 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18163 && (glyph + 1)->charpos == ellipsis_pos)
18164 glyph++, x += glyph->pixel_width;
18165 x -= glyph->pixel_width;
18166 glyph--;
18167 }
18168 }
18169 else if (match_with_avoid_cursor)
18170 {
18171 cursor = glyph_after;
18172 x = -1;
18173 }
18174 else if (string_seen)
18175 {
18176 int incr = row->reversed_p ? -1 : +1;
18177
18178
18179
18180
18181
18182
18183 struct glyph *start, *stop;
18184 ptrdiff_t pos = pos_before;
18185
18186 x = -1;
18187
18188
18189
18190
18191
18192
18193 if (row->ends_in_newline_from_string_p)
18194 {
18195 glyph_after = end;
18196 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18197 }
18198
18199
18200
18201
18202
18203
18204
18205
18206
18207 if (!row->reversed_p)
18208 {
18209 start = min (glyph_before, glyph_after);
18210 stop = max (glyph_before, glyph_after);
18211 }
18212 else
18213 {
18214 start = max (glyph_before, glyph_after);
18215 stop = min (glyph_before, glyph_after);
18216 }
18217 for (glyph = start + incr;
18218 row->reversed_p ? glyph > stop : glyph < stop; )
18219 {
18220
18221
18222
18223
18224 if (STRINGP (glyph->object))
18225 {
18226 Lisp_Object str;
18227 ptrdiff_t tem;
18228
18229
18230 ptrdiff_t lim = pos_after
18231 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18232
18233 string_from_text_prop = false;
18234 str = glyph->object;
18235 tem = string_buffer_position_lim (str, pos, lim, false);
18236 if (tem == 0
18237 || pos <= tem)
18238 {
18239
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249 if (tem == 0
18250 || tem == pt_old
18251 || (tem - pt_old > 0 && tem < pos_after))
18252 {
18253
18254
18255
18256
18257
18258
18259 ptrdiff_t strpos = glyph->charpos;
18260
18261 if (tem)
18262 {
18263 cursor = glyph;
18264 string_from_text_prop = true;
18265 }
18266 for ( ;
18267 (row->reversed_p ? glyph > stop : glyph < stop)
18268 && EQ (glyph->object, str);
18269 glyph += incr)
18270 {
18271 Lisp_Object cprop;
18272 ptrdiff_t gpos = glyph->charpos;
18273
18274 cprop = Fget_char_property (make_fixnum (gpos),
18275 Qcursor,
18276 glyph->object);
18277 if (!NILP (cprop))
18278 {
18279 cursor = glyph;
18280 break;
18281 }
18282 if (tem && glyph->charpos < strpos)
18283 {
18284 strpos = glyph->charpos;
18285 cursor = glyph;
18286 }
18287 }
18288
18289 if (tem == pt_old
18290 || (tem - pt_old > 0 && tem < pos_after))
18291 goto compute_x;
18292 }
18293 if (tem)
18294 pos = tem + 1;
18295 }
18296
18297
18298 while ((row->reversed_p ? glyph > stop : glyph < stop)
18299 && EQ (glyph->object, str))
18300 glyph += incr;
18301 }
18302 else
18303 glyph += incr;
18304 }
18305
18306
18307
18308 if (cursor == NULL
18309 && (row->reversed_p ? glyph <= end : glyph >= end)
18310 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18311 && STRINGP (end->object)
18312 && row->continued_p)
18313 return false;
18314 }
18315
18316
18317
18318
18319
18320 else if (row->truncated_on_left_p && pt_old < bpos_min)
18321 {
18322 cursor = glyph_before;
18323 x = -1;
18324 }
18325 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18326
18327 || (!empty_line_p
18328 && (row->reversed_p
18329 ? glyph_after > glyphs_end
18330 : glyph_after < glyphs_end)))
18331 {
18332 cursor = glyph_after;
18333 x = -1;
18334 }
18335 }
18336
18337 compute_x:
18338 if (cursor != NULL)
18339 glyph = cursor;
18340 else if (glyph == glyphs_end
18341 && pos_before == pos_after
18342 && STRINGP ((row->reversed_p
18343 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18344 : row->glyphs[TEXT_AREA])->object))
18345 {
18346
18347
18348
18349
18350 glyph =
18351 row->reversed_p
18352 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18353 : row->glyphs[TEXT_AREA];
18354 }
18355 if (x < 0)
18356 {
18357 struct glyph *g;
18358
18359
18360 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18361 {
18362 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18363 emacs_abort ();
18364 x += g->pixel_width;
18365 }
18366 }
18367
18368
18369
18370
18371
18372
18373 if (
18374 w->cursor.vpos >= 0
18375
18376 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18377
18378
18379
18380
18381
18382 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18383 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18384 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18385 {
18386 struct glyph *g1
18387 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18388
18389
18390 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18391 return false;
18392
18393
18394 if (
18395 w->cursor.hpos >= 0
18396 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18397 && ((BUFFERP (g1->object)
18398 && (g1->charpos == pt_old
18399 || (BUFFERP (glyph->object)
18400 && eabs (g1->charpos - pt_old)
18401 < eabs (glyph->charpos - pt_old))))
18402
18403
18404 || (STRINGP (g1->object)
18405 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18406 Qcursor, g1->object))
18407
18408
18409
18410 || (EQ (g1->object, glyph->object)
18411 && string_from_text_prop)
18412
18413
18414 || (NILP (glyph->object)
18415 && glyph->charpos != pt_old)))))
18416 return false;
18417
18418 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18419
18420
18421
18422 || (!row->continued_p
18423 && NILP (glyph->object)
18424 && glyph->charpos == 0
18425 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18426
18427
18428
18429
18430
18431 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18432 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18433 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18434 return false;
18435 }
18436 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18437 w->cursor.x = x;
18438 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18439 w->cursor.y = row->y + dy;
18440
18441 if (w == XWINDOW (selected_window))
18442 {
18443 if (!row->continued_p
18444 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18445 && row->x == 0)
18446 {
18447 this_line_buffer = XBUFFER (w->contents);
18448
18449 CHARPOS (this_line_start_pos)
18450 = MATRIX_ROW_START_CHARPOS (row) + delta;
18451 BYTEPOS (this_line_start_pos)
18452 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18453
18454 CHARPOS (this_line_end_pos)
18455 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18456 BYTEPOS (this_line_end_pos)
18457 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18458
18459 this_line_y = w->cursor.y;
18460 this_line_pixel_height = row->height;
18461 this_line_vpos = w->cursor.vpos;
18462 this_line_start_x = row->x;
18463 }
18464 else
18465 CHARPOS (this_line_start_pos) = 0;
18466 }
18467
18468 return true;
18469 }
18470
18471
18472
18473
18474
18475
18476
18477 static struct text_pos
18478 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18479 {
18480 struct window *w = XWINDOW (window);
18481 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18482
18483 eassert (current_buffer == XBUFFER (w->contents));
18484
18485 if (!NILP (Vwindow_scroll_functions))
18486 {
18487 specpdl_ref count = SPECPDL_INDEX ();
18488 specbind (Qinhibit_quit, Qt);
18489 safe_run_hooks_2
18490 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18491 unbind_to (count, Qnil);
18492 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18493
18494 set_buffer_internal (XBUFFER (w->contents));
18495 }
18496
18497 return startp;
18498 }
18499
18500
18501
18502
18503
18504
18505
18506
18507
18508
18509
18510
18511
18512
18513
18514
18515
18516
18517
18518
18519
18520
18521 static bool
18522 cursor_row_fully_visible_p (struct window *w, bool force_p,
18523 bool current_matrix_p,
18524 bool just_test_user_preference_p)
18525 {
18526 struct glyph_matrix *matrix;
18527 struct glyph_row *row;
18528 int window_height;
18529 Lisp_Object mclfv_p =
18530 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18531
18532
18533 if (BASE_EQ (mclfv_p, Qunbound))
18534 mclfv_p = Vmake_cursor_line_fully_visible;
18535
18536
18537 if (FUNCTIONP (mclfv_p))
18538 {
18539 Lisp_Object window;
18540 XSETWINDOW (window, w);
18541
18542
18543 Lisp_Object val = safe_call1 (mclfv_p, window);
18544 if (NILP (val))
18545 return true;
18546 else if (just_test_user_preference_p)
18547 return false;
18548 }
18549 else if (NILP (mclfv_p))
18550 return true;
18551 else if (just_test_user_preference_p)
18552 return false;
18553
18554
18555
18556 if (w->cursor.vpos < 0)
18557 return true;
18558
18559 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18560 row = MATRIX_ROW (matrix, w->cursor.vpos);
18561
18562
18563 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18564 return true;
18565
18566
18567
18568 window_height = window_box_height (w);
18569 if (row->height >= window_height)
18570 {
18571 if (!force_p || MINI_WINDOW_P (w)
18572 || w->vscroll || w->cursor.vpos == 0)
18573 return true;
18574 }
18575 return false;
18576 }
18577
18578
18579
18580
18581
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597 enum
18598 {
18599 SCROLLING_SUCCESS = 1,
18600 SCROLLING_FAILED = 0,
18601 SCROLLING_NEED_LARGER_MATRICES = -1
18602 };
18603
18604
18605
18606
18607
18608 #define SCROLL_LIMIT 100
18609
18610 static int
18611 try_scrolling (Lisp_Object window, bool just_this_one_p,
18612 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18613 bool temp_scroll_step, bool last_line_misfit)
18614 {
18615 struct window *w = XWINDOW (window);
18616 struct text_pos pos, startp;
18617 struct it it;
18618 int this_scroll_margin, scroll_max, rc, height;
18619 int dy = 0, amount_to_scroll = 0;
18620 bool scroll_down_p = false;
18621 int extra_scroll_margin_lines = last_line_misfit;
18622 Lisp_Object aggressive;
18623
18624 int scroll_limit = SCROLL_LIMIT;
18625 int frame_line_height = default_line_pixel_height (w);
18626
18627 #ifdef GLYPH_DEBUG
18628 debug_method_add (w, "try_scrolling");
18629 #endif
18630
18631 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18632
18633 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18634
18635
18636
18637
18638
18639 if (arg_scroll_conservatively > scroll_limit)
18640 {
18641 arg_scroll_conservatively = scroll_limit + 1;
18642 scroll_max = scroll_limit * frame_line_height;
18643 }
18644 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18645
18646
18647 {
18648 intmax_t scroll_lines_max
18649 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18650 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18651 scroll_max = scroll_lines * frame_line_height;
18652 }
18653 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18654 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18655
18656
18657 scroll_max = 10 * frame_line_height;
18658 else
18659 scroll_max = 0;
18660
18661 too_near_end:
18662
18663
18664 if (PT > CHARPOS (startp))
18665 {
18666 int scroll_margin_y;
18667
18668
18669
18670 start_display (&it, w, startp);
18671 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18672 - this_scroll_margin
18673 - frame_line_height * extra_scroll_margin_lines;
18674 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18675 (MOVE_TO_POS | MOVE_TO_Y));
18676
18677 if (PT > CHARPOS (it.current.pos))
18678 {
18679 int y0 = line_bottom_y (&it);
18680
18681
18682
18683
18684
18685 int slack = max (scroll_max, 10 * frame_line_height);
18686 int y_to_move = it.last_visible_y + slack;
18687
18688
18689
18690
18691
18692 move_it_to (&it, PT, -1, y_to_move,
18693 -1, MOVE_TO_POS | MOVE_TO_Y);
18694 dy = line_bottom_y (&it) - y0;
18695
18696 if (dy > scroll_max)
18697 return SCROLLING_FAILED;
18698
18699 if (dy > 0)
18700 scroll_down_p = true;
18701 }
18702 else if (PT == IT_CHARPOS (it)
18703 && IT_CHARPOS (it) < ZV
18704 && it.method == GET_FROM_STRING
18705 && arg_scroll_conservatively > scroll_limit
18706 && it.current_x == 0)
18707 {
18708 enum move_it_result skip;
18709 int y1 = it.current_y;
18710 int vpos;
18711
18712
18713
18714
18715
18716
18717
18718 do {
18719 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18720 if (skip != MOVE_NEWLINE_OR_CR
18721 || IT_CHARPOS (it) != PT
18722 || it.method == GET_FROM_BUFFER)
18723 break;
18724 vpos = it.vpos;
18725 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18726 } while (it.vpos > vpos);
18727
18728 dy = it.current_y - y1;
18729
18730 if (dy > scroll_max)
18731 return SCROLLING_FAILED;
18732
18733 if (dy > 0)
18734 scroll_down_p = true;
18735 }
18736 }
18737
18738 if (scroll_down_p)
18739 {
18740
18741
18742
18743
18744 if (arg_scroll_conservatively)
18745 amount_to_scroll
18746 = min (max (dy, frame_line_height),
18747 frame_line_height * arg_scroll_conservatively);
18748 else if (scroll_step || temp_scroll_step)
18749 amount_to_scroll = scroll_max;
18750 else
18751 {
18752 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18753 height = WINDOW_BOX_TEXT_HEIGHT (w);
18754 if (NUMBERP (aggressive))
18755 {
18756 double float_amount = XFLOATINT (aggressive) * height;
18757 int aggressive_scroll = float_amount;
18758 if (aggressive_scroll == 0 && float_amount > 0)
18759 aggressive_scroll = 1;
18760
18761
18762
18763
18764
18765
18766 if (aggressive_scroll + 2 * this_scroll_margin > height)
18767 aggressive_scroll = height - 2 * this_scroll_margin;
18768 amount_to_scroll = dy + aggressive_scroll;
18769 }
18770 }
18771
18772 if (amount_to_scroll <= 0)
18773 return SCROLLING_FAILED;
18774
18775 start_display (&it, w, startp);
18776 if (arg_scroll_conservatively <= scroll_limit)
18777 move_it_vertically (&it, amount_to_scroll);
18778 else
18779 {
18780
18781
18782
18783
18784
18785
18786 struct it it1;
18787 void *it1data = NULL;
18788
18789
18790 int start_y;
18791
18792 SAVE_IT (it1, it, it1data);
18793 start_y = line_bottom_y (&it1);
18794 do {
18795 RESTORE_IT (&it, &it, it1data);
18796 move_it_by_lines (&it, 1);
18797 SAVE_IT (it1, it, it1data);
18798 } while (IT_CHARPOS (it) < ZV
18799 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18800 bidi_unshelve_cache (it1data, true);
18801 }
18802
18803
18804 if (IT_CHARPOS (it) == CHARPOS (startp))
18805 move_it_by_lines (&it, 1);
18806 startp = it.current.pos;
18807 }
18808 else
18809 {
18810 struct text_pos scroll_margin_pos = startp;
18811 int y_offset = 0;
18812
18813
18814
18815 if (this_scroll_margin)
18816 {
18817 int y_start;
18818
18819 start_display (&it, w, startp);
18820 y_start = it.current_y;
18821 move_it_vertically (&it, this_scroll_margin);
18822 scroll_margin_pos = it.current.pos;
18823
18824
18825
18826 if (IT_CHARPOS (it) == ZV
18827 && it.current_y - y_start < this_scroll_margin)
18828 y_offset = this_scroll_margin - (it.current_y - y_start);
18829 }
18830
18831 if (PT < CHARPOS (scroll_margin_pos))
18832 {
18833
18834
18835 int y0, y_to_move;
18836
18837
18838
18839
18840
18841
18842 SET_TEXT_POS (pos, PT, PT_BYTE);
18843 start_display (&it, w, pos);
18844 y0 = it.current_y;
18845 y_to_move = max (it.last_visible_y,
18846 max (scroll_max, 10 * frame_line_height));
18847 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18848 y_to_move, -1,
18849 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18850 dy = it.current_y - y0;
18851 if (dy > scroll_max
18852 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18853 return SCROLLING_FAILED;
18854
18855
18856 dy += y_offset;
18857
18858
18859 start_display (&it, w, startp);
18860
18861 if (arg_scroll_conservatively)
18862 amount_to_scroll
18863 = min (max (dy, frame_line_height),
18864 frame_line_height * arg_scroll_conservatively);
18865 else if (scroll_step || temp_scroll_step)
18866 amount_to_scroll = scroll_max;
18867 else
18868 {
18869 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18870 height = WINDOW_BOX_TEXT_HEIGHT (w);
18871 if (NUMBERP (aggressive))
18872 {
18873 double float_amount = XFLOATINT (aggressive) * height;
18874 int aggressive_scroll = float_amount;
18875 if (aggressive_scroll == 0 && float_amount > 0)
18876 aggressive_scroll = 1;
18877
18878
18879
18880
18881 if (aggressive_scroll + 2 * this_scroll_margin > height)
18882 aggressive_scroll = height - 2 * this_scroll_margin;
18883 amount_to_scroll = dy + aggressive_scroll;
18884 }
18885 }
18886
18887 if (amount_to_scroll <= 0)
18888 return SCROLLING_FAILED;
18889
18890 move_it_vertically_backward (&it, amount_to_scroll);
18891 startp = it.current.pos;
18892 }
18893 }
18894
18895
18896 startp = run_window_scroll_functions (window, startp);
18897
18898
18899
18900 if (!try_window (window, startp, 0))
18901 rc = SCROLLING_NEED_LARGER_MATRICES;
18902 else if (w->cursor.vpos < 0)
18903 {
18904 clear_glyph_matrix (w->desired_matrix);
18905 rc = SCROLLING_FAILED;
18906 }
18907 else
18908 {
18909
18910 if (!just_this_one_p
18911 || current_buffer->clip_changed
18912 || BEG_UNCHANGED < CHARPOS (startp))
18913 w->base_line_number = 0;
18914
18915
18916
18917 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18918 false, false)
18919
18920
18921
18922 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18923 {
18924 clear_glyph_matrix (w->desired_matrix);
18925 ++extra_scroll_margin_lines;
18926 goto too_near_end;
18927 }
18928 rc = SCROLLING_SUCCESS;
18929 }
18930
18931 return rc;
18932 }
18933
18934
18935
18936
18937
18938
18939
18940
18941
18942
18943
18944
18945 static bool
18946 compute_window_start_on_continuation_line (struct window *w)
18947 {
18948 struct text_pos pos, start_pos, pos_before_pt;
18949 bool window_start_changed_p = false;
18950
18951 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18952
18953
18954
18955
18956 if (CHARPOS (start_pos) > BEGV
18957 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18958 {
18959 struct it it;
18960 struct glyph_row *row;
18961
18962
18963 if (CHARPOS (start_pos) < BEGV)
18964 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18965 else if (CHARPOS (start_pos) > ZV)
18966 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18967
18968
18969
18970 row = w->desired_matrix->rows + window_wants_tab_line (w)
18971 + window_wants_header_line (w);
18972 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18973 row, DEFAULT_FACE_ID);
18974 reseat_at_previous_visible_line_start (&it);
18975
18976
18977
18978
18979
18980
18981
18982 if (IT_CHARPOS (it) <= PT
18983 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18984
18985 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18986 {
18987 int min_distance, distance;
18988
18989
18990
18991
18992
18993
18994
18995 pos_before_pt = pos = it.current.pos;
18996 min_distance = DISP_INFINITY;
18997 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18998 distance < min_distance)
18999 {
19000 min_distance = distance;
19001 if (CHARPOS (pos) <= PT)
19002 pos_before_pt = pos;
19003 pos = it.current.pos;
19004 if (it.line_wrap == WORD_WRAP)
19005 {
19006
19007
19008
19009
19010
19011
19012
19013
19014
19015 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
19016 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19017 move_it_to (&it, ZV, 0,
19018 it.current_y + it.max_ascent + it.max_descent, -1,
19019 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19020 }
19021 else
19022 move_it_by_lines (&it, 1);
19023 }
19024
19025
19026
19027
19028
19029 if (CHARPOS (pos) > PT)
19030 pos = pos_before_pt;
19031
19032
19033 SET_MARKER_FROM_TEXT_POS (w->start, pos);
19034 window_start_changed_p = true;
19035 }
19036 }
19037
19038 return window_start_changed_p;
19039 }
19040
19041
19042
19043
19044
19045
19046
19047
19048
19049
19050
19051
19052
19053
19054
19055
19056
19057 enum
19058 {
19059 CURSOR_MOVEMENT_SUCCESS,
19060 CURSOR_MOVEMENT_CANNOT_BE_USED,
19061 CURSOR_MOVEMENT_MUST_SCROLL,
19062 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
19063 };
19064
19065 static int
19066 try_cursor_movement (Lisp_Object window, struct text_pos startp,
19067 bool *scroll_step)
19068 {
19069 struct window *w = XWINDOW (window);
19070 struct frame *f = XFRAME (w->frame);
19071 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
19072
19073 #ifdef GLYPH_DEBUG
19074 if (inhibit_try_cursor_movement)
19075 return rc;
19076 #endif
19077
19078
19079
19080
19081 eassert (w->last_point > 0);
19082
19083
19084
19085 eassert (!w->window_end_valid
19086 || w->window_end_vpos < w->current_matrix->nrows);
19087
19088
19089
19090 if (
19091 PT >= CHARPOS (startp)
19092
19093 && !current_buffer->clip_changed
19094
19095
19096
19097
19098 && !update_mode_lines
19099 && !windows_or_buffers_changed
19100 && !f->cursor_type_changed
19101 && NILP (Vshow_trailing_whitespace)
19102
19103
19104 && !EQ (Vdisplay_line_numbers, Qrelative)
19105 && !EQ (Vdisplay_line_numbers, Qvisual)
19106
19107
19108
19109 && !(!NILP (Vdisplay_line_numbers)
19110 && NILP (Finternal_lisp_face_equal_p (Qline_number,
19111 Qline_number_current_line,
19112 w->frame)))
19113
19114
19115
19116
19117
19118
19119 && !EQ (window, minibuf_window)
19120
19121
19122
19123 && !overlay_arrow_in_current_buffer_p ())
19124 {
19125 int this_scroll_margin, top_scroll_margin;
19126 struct glyph_row *row = NULL;
19127
19128 #ifdef GLYPH_DEBUG
19129 debug_method_add (w, "cursor movement");
19130 #endif
19131
19132 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
19133
19134 top_scroll_margin = this_scroll_margin;
19135 if (window_wants_tab_line (w))
19136 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
19137 if (window_wants_header_line (w))
19138 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
19139
19140
19141
19142 if (w->last_cursor_vpos < 0
19143 || w->last_cursor_vpos >= w->current_matrix->nrows)
19144 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19145 else
19146 {
19147 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
19148
19149 if (row->tab_line_p)
19150 ++row;
19151 if (row->mode_line_p)
19152 ++row;
19153 if (!row->enabled_p)
19154 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19155 }
19156
19157 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
19158 {
19159 bool scroll_p = false, must_scroll = false;
19160 int last_y = window_text_bottom_y (w) - this_scroll_margin;
19161
19162 if (PT > w->last_point)
19163 {
19164
19165 while (MATRIX_ROW_END_CHARPOS (row) < PT
19166 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19167 {
19168 eassert (row->enabled_p);
19169 ++row;
19170 }
19171
19172
19173
19174
19175 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19176 && MATRIX_ROW_END_CHARPOS (row) == PT
19177 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
19178 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19179 && !cursor_row_p (row))
19180 ++row;
19181
19182
19183
19184
19185
19186 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19187 || PT > MATRIX_ROW_END_CHARPOS (row)
19188
19189
19190 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19191 && PT == MATRIX_ROW_END_CHARPOS (row)
19192 && !row->ends_at_zv_p
19193 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19194 scroll_p = true;
19195 }
19196 else if (PT < w->last_point)
19197 {
19198
19199
19200 struct glyph_row *row0 = row;
19201
19202 while (!row->mode_line_p
19203 && (MATRIX_ROW_START_CHARPOS (row) > PT
19204 || (MATRIX_ROW_START_CHARPOS (row) == PT
19205 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19206 || (
19207 row > w->current_matrix->rows
19208 && (row-1)->ends_in_newline_from_string_p))))
19209 && (row->y > top_scroll_margin
19210 || CHARPOS (startp) == BEGV))
19211 {
19212 eassert (row->enabled_p);
19213 --row;
19214 }
19215
19216
19217
19218
19219
19220 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19221 && PT <= MATRIX_ROW_END_CHARPOS (row))
19222 && row0->continued_p)
19223 {
19224 row = row0;
19225 while (MATRIX_ROW_START_CHARPOS (row) > PT
19226 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19227 {
19228 eassert (row->enabled_p);
19229 ++row;
19230 }
19231 }
19232
19233
19234
19235
19236
19237
19238 if (row < w->current_matrix->rows
19239 || row->mode_line_p)
19240 {
19241 row = w->current_matrix->rows;
19242
19243 if (row->tab_line_p)
19244 ++row;
19245 if (row->mode_line_p)
19246 ++row;
19247 }
19248
19249
19250
19251 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19252 && MATRIX_ROW_END_CHARPOS (row) == PT
19253 && !cursor_row_p (row))
19254 ++row;
19255
19256
19257
19258 if ((row->y < top_scroll_margin
19259 && CHARPOS (startp) != BEGV)
19260 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19261 || PT > MATRIX_ROW_END_CHARPOS (row)
19262 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19263 && PT == MATRIX_ROW_END_CHARPOS (row)
19264 && !row->ends_at_zv_p
19265 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19266 scroll_p = true;
19267 }
19268 else
19269 {
19270
19271
19272 rc = CURSOR_MOVEMENT_SUCCESS;
19273 }
19274
19275 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19276 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19277
19278
19279 || (MATRIX_ROW_END_CHARPOS (row-1)
19280 == MATRIX_ROW_START_CHARPOS (row))))
19281 || PT > MATRIX_ROW_END_CHARPOS (row))
19282 {
19283
19284 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19285 must_scroll = true;
19286 }
19287 else if (rc != CURSOR_MOVEMENT_SUCCESS
19288 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19289 {
19290 struct glyph_row *row1;
19291
19292
19293
19294
19295
19296
19297
19298
19299
19300
19301
19302 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19303 MATRIX_ROW_CONTINUATION_LINE_P (row);
19304 --row)
19305 {
19306
19307
19308
19309 if (row <= row1)
19310 {
19311 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19312 break;
19313 }
19314 eassert (row->enabled_p);
19315 }
19316 }
19317 if (must_scroll)
19318 ;
19319 else if (rc != CURSOR_MOVEMENT_SUCCESS
19320 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19321
19322
19323
19324 && !row->mode_line_p
19325 && !cursor_row_fully_visible_p (w, true, true, true))
19326 {
19327 if (PT == MATRIX_ROW_END_CHARPOS (row)
19328 && !row->ends_at_zv_p
19329 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19330 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19331 else if (row->height > window_box_height (w))
19332 {
19333
19334
19335
19336
19337 *scroll_step = true;
19338 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19339 }
19340 else
19341 {
19342 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19343 if (!cursor_row_fully_visible_p (w, false, true, false))
19344 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19345 else
19346 rc = CURSOR_MOVEMENT_SUCCESS;
19347 }
19348 }
19349 else if (scroll_p)
19350 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19351 else if (rc != CURSOR_MOVEMENT_SUCCESS
19352 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19353 {
19354
19355
19356
19357
19358
19359
19360
19361 bool rv = false;
19362 bool pt_invis = false;
19363 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19364 Qinvisible,
19365 Qnil, NULL);
19366
19367 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19368 pt_invis = true;
19369
19370 do
19371 {
19372 bool at_zv_p = false, exact_match_p = false;
19373
19374
19375
19376
19377
19378 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19379 && PT <= MATRIX_ROW_END_CHARPOS (row)
19380 && cursor_row_p (row))
19381 rv |= set_cursor_from_row (w, row, w->current_matrix,
19382 0, 0, 0, 0);
19383
19384
19385
19386 if (rv)
19387 {
19388 at_zv_p = MATRIX_ROW (w->current_matrix,
19389 w->cursor.vpos)->ends_at_zv_p;
19390 if (!at_zv_p
19391 && w->cursor.hpos >= 0
19392 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19393 w->cursor.vpos))
19394 {
19395 struct glyph_row *candidate =
19396 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19397 struct glyph *g =
19398 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19399 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19400
19401 exact_match_p =
19402 (BUFFERP (g->object) && g->charpos == PT)
19403 || (NILP (g->object)
19404 && (g->charpos == PT
19405 || (g->charpos == 0 && endpos - 1 == PT)));
19406
19407
19408
19409
19410 if (!exact_match_p && pt_invis)
19411 exact_match_p = true;
19412 }
19413 if (at_zv_p || exact_match_p)
19414 {
19415 rc = CURSOR_MOVEMENT_SUCCESS;
19416 break;
19417 }
19418 }
19419 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19420 break;
19421 ++row;
19422 }
19423 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19424 || row->continued_p)
19425 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19426 || (MATRIX_ROW_START_CHARPOS (row) == PT
19427 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19428
19429
19430
19431 if (rc != CURSOR_MOVEMENT_SUCCESS
19432 && !(rv
19433 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19434 && !row->continued_p))
19435 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19436 else if (rv)
19437 rc = CURSOR_MOVEMENT_SUCCESS;
19438 }
19439 else
19440 {
19441 do
19442 {
19443 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19444 {
19445 rc = CURSOR_MOVEMENT_SUCCESS;
19446 break;
19447 }
19448 ++row;
19449 }
19450 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19451 && MATRIX_ROW_START_CHARPOS (row) == PT
19452 && cursor_row_p (row));
19453 }
19454 }
19455 }
19456
19457 return rc;
19458 }
19459
19460
19461 void
19462 set_vertical_scroll_bar (struct window *w)
19463 {
19464 ptrdiff_t start, end, whole;
19465
19466
19467
19468
19469
19470
19471
19472
19473 if (!MINI_WINDOW_P (w)
19474 || (w == XWINDOW (minibuf_window)
19475 && NILP (echo_area_buffer[0])))
19476 {
19477 struct buffer *buf = XBUFFER (w->contents);
19478
19479 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19480 start = marker_position (w->start) - BUF_BEGV (buf);
19481 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19482
19483
19484
19485
19486 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19487 {
19488 struct it it;
19489 struct text_pos start_pos;
19490 struct buffer *obuf = current_buffer;
19491
19492
19493
19494 set_buffer_internal_1 (XBUFFER (w->contents));
19495 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19496 start_display (&it, w, start_pos);
19497 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19498 MOVE_TO_X | MOVE_TO_Y);
19499 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19500 set_buffer_internal_1 (obuf);
19501 }
19502
19503 if (end < start)
19504 end = start;
19505 if (whole < (end - start))
19506 whole = end - start;
19507 }
19508 else
19509 start = end = whole = 0;
19510
19511
19512 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19513 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19514 (w, end - start, whole, start);
19515 }
19516
19517
19518 void
19519 set_horizontal_scroll_bar (struct window *w)
19520 {
19521 int start, end, whole, portion;
19522
19523 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19524 {
19525 struct buffer *b = XBUFFER (w->contents);
19526 struct buffer *old_buffer = NULL;
19527 struct it it;
19528 struct text_pos startp;
19529
19530 if (b != current_buffer)
19531 {
19532 old_buffer = current_buffer;
19533 set_buffer_internal (b);
19534 }
19535
19536 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19537 start_display (&it, w, startp);
19538 it.last_visible_x = INT_MAX;
19539 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19540 MOVE_TO_X | MOVE_TO_Y);
19541
19542
19543
19544
19545 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19546 end = start + window_box_width (w, TEXT_AREA);
19547 portion = end - start;
19548
19549
19550
19551
19552 whole = max (whole, end);
19553
19554 if (it.bidi_p)
19555 {
19556 Lisp_Object pdir;
19557
19558 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19559 if (EQ (pdir, Qright_to_left))
19560 {
19561 start = whole - end;
19562 end = start + portion;
19563 }
19564 }
19565
19566 if (old_buffer)
19567 set_buffer_internal (old_buffer);
19568 }
19569 else
19570 start = end = whole = portion = 0;
19571
19572 w->hscroll_whole = whole;
19573
19574
19575 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19576 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19577 (w, portion, whole, start);
19578 }
19579
19580
19581
19582 static bool
19583 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19584 {
19585 if (!make_window_start_visible)
19586 return true;
19587
19588 struct window *w = XWINDOW (window);
19589 struct frame *f = XFRAME (w->frame);
19590 Lisp_Object startpos = make_fixnum (startp);
19591 Lisp_Object invprop, disp_spec;
19592 struct text_pos ignored;
19593
19594
19595 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19596 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19597 return false;
19598
19599
19600 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19601 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19602 FRAME_WINDOW_P (f)) > 0)
19603 return false;
19604
19605 return true;
19606 }
19607
19608 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19609 0, 0, 0,
19610 doc:
19611
19612 )
19613 (void)
19614 {
19615 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19616 }
19617
19618
19619
19620
19621
19622
19623
19624
19625
19626
19627
19628
19629
19630
19631
19632
19633
19634
19635
19636
19637
19638
19639
19640
19641
19642
19643
19644
19645
19646
19647
19648
19649
19650
19651
19652
19653
19654
19655
19656
19657
19658
19659
19660
19661
19662
19663
19664
19665
19666
19667
19668 static void
19669 redisplay_window (Lisp_Object window, bool just_this_one_p)
19670 {
19671 struct window *w = XWINDOW (window);
19672 struct frame *f = XFRAME (w->frame);
19673 struct buffer *buffer = XBUFFER (w->contents);
19674 struct buffer *old = current_buffer;
19675 struct text_pos lpoint, opoint, startp;
19676 bool update_mode_line;
19677 int tem;
19678 struct it it;
19679
19680 bool current_matrix_up_to_date_p = false;
19681 bool used_current_matrix_p = false;
19682
19683
19684 bool buffer_unchanged_p = false;
19685 bool temp_scroll_step = false;
19686 specpdl_ref count = SPECPDL_INDEX ();
19687 int rc;
19688 int centering_position = -1;
19689 bool last_line_misfit = false;
19690 ptrdiff_t beg_unchanged, end_unchanged;
19691 int frame_line_height, margin;
19692 bool use_desired_matrix;
19693 void *itdata = NULL;
19694
19695 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19696 opoint = lpoint;
19697
19698 #ifdef GLYPH_DEBUG
19699 *w->desired_matrix->method = 0;
19700 #endif
19701
19702 if (!just_this_one_p && needs_no_redisplay (w))
19703 return;
19704
19705
19706 eassert (XMARKER (w->start)->buffer == buffer);
19707 eassert (XMARKER (w->pointm)->buffer == buffer);
19708
19709 reconsider_clip_changes (w);
19710 frame_line_height = default_line_pixel_height (w);
19711 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19712
19713
19714
19715 update_mode_line = (w->update_mode_line
19716 || update_mode_lines
19717 || buffer->clip_changed
19718 || buffer->prevent_redisplay_optimizations_p);
19719
19720 if (!just_this_one_p)
19721
19722
19723 w->must_be_updated_p = true;
19724
19725 if (MINI_WINDOW_P (w))
19726 {
19727 if (w == XWINDOW (echo_area_window)
19728 && !NILP (echo_area_buffer[0]))
19729 {
19730 if (update_mode_line)
19731
19732
19733 goto finish_menu_bars;
19734 else
19735
19736 goto finish_scroll_bars;
19737 }
19738 else if ((w != XWINDOW (minibuf_window)
19739 || minibuf_level == 0)
19740
19741 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19742
19743
19744 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19745 {
19746
19747
19748 int yb = window_text_bottom_y (w);
19749 struct glyph_row *row;
19750 int y;
19751
19752 for (y = 0, row = w->desired_matrix->rows;
19753 y < yb;
19754 y += row->height, ++row)
19755 blank_row (w, row, y);
19756 goto finish_scroll_bars;
19757 }
19758 else if (minibuf_level >= 1)
19759 {
19760
19761
19762
19763 resize_mini_window (w, false);
19764 }
19765
19766 clear_glyph_matrix (w->desired_matrix);
19767 }
19768
19769
19770
19771
19772
19773 set_buffer_internal_1 (XBUFFER (w->contents));
19774
19775 current_matrix_up_to_date_p
19776 = (w->window_end_valid
19777 && !current_buffer->clip_changed
19778 && !current_buffer->prevent_redisplay_optimizations_p
19779 && !window_outdated (w)
19780 && !composition_break_at_point
19781 && !hscrolling_current_line_p (w));
19782
19783 beg_unchanged = BEG_UNCHANGED;
19784 end_unchanged = END_UNCHANGED;
19785
19786 SET_TEXT_POS (opoint, PT, PT_BYTE);
19787
19788 specbind (Qinhibit_point_motion_hooks, Qt);
19789
19790 buffer_unchanged_p
19791 = (w->window_end_valid
19792 && !current_buffer->clip_changed
19793 && !window_outdated (w));
19794
19795
19796
19797 if (windows_or_buffers_changed)
19798 {
19799
19800
19801 if (XMARKER (w->start)->buffer == current_buffer)
19802 compute_window_start_on_continuation_line (w);
19803
19804 w->window_end_valid = false;
19805
19806
19807 current_matrix_up_to_date_p = false;
19808 }
19809
19810
19811 CHECK_WINDOW_END (w);
19812 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19813 emacs_abort ();
19814 if (BYTEPOS (opoint) < CHARPOS (opoint))
19815 emacs_abort ();
19816
19817 if (mode_line_update_needed (w))
19818 update_mode_line = true;
19819
19820
19821
19822 if (!EQ (window, selected_window))
19823 {
19824 ptrdiff_t new_pt = marker_position (w->pointm);
19825 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19826
19827 if (new_pt < BEGV)
19828 {
19829 new_pt = BEGV;
19830 new_pt_byte = BEGV_BYTE;
19831 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19832 }
19833 else if (new_pt > (ZV - 1))
19834 {
19835 new_pt = ZV;
19836 new_pt_byte = ZV_BYTE;
19837 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19838 }
19839
19840
19841 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19842 }
19843
19844
19845
19846
19847
19848
19849 if (current_buffer->width_run_cache
19850 || (current_buffer->base_buffer
19851 && current_buffer->base_buffer->width_run_cache))
19852 {
19853 struct Lisp_Char_Table *disptab = buffer_display_table ();
19854
19855 if (! disptab_matches_widthtab
19856 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19857 {
19858 struct buffer *buf = current_buffer;
19859
19860 if (buf->base_buffer)
19861 buf = buf->base_buffer;
19862 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19863 recompute_width_table (current_buffer, disptab);
19864 }
19865 }
19866
19867
19868 if (!NILP (Vlong_line_threshold)
19869 && !current_buffer->long_line_optimizations_p
19870 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19871 || current_buffer->clip_changed))
19872 {
19873 ptrdiff_t cur, next, found, max = 0, threshold;
19874 threshold = XFIXNUM (Vlong_line_threshold);
19875 for (cur = BEGV; cur < ZV; cur = next)
19876 {
19877 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19878 &found, NULL, true);
19879 if (next - cur > max) max = next - cur;
19880 if (!found || max > threshold) break;
19881 }
19882 if (max > threshold)
19883 current_buffer->long_line_optimizations_p = true;
19884 }
19885
19886
19887 if (XMARKER (w->start)->buffer != current_buffer)
19888 goto recenter;
19889
19890 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19891
19892
19893
19894 if ((w->optional_new_start || window_frozen_p (w))
19895 && CHARPOS (startp) >= BEGV
19896 && CHARPOS (startp) <= ZV)
19897 {
19898 ptrdiff_t it_charpos;
19899
19900 w->optional_new_start = false;
19901 if (!w->force_start)
19902 {
19903 start_display (&it, w, startp);
19904 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19905 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19906
19907
19908 it_charpos = IT_CHARPOS (it);
19909
19910
19911
19912
19913
19914 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19915 {
19916 if (it_charpos == PT)
19917 w->force_start = true;
19918
19919 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19920 w->force_start = true;
19921 #ifdef GLYPH_DEBUG
19922 if (w->force_start)
19923 {
19924 if (window_frozen_p (w))
19925 debug_method_add (w, "set force_start from frozen window start");
19926 else
19927 debug_method_add (w, "set force_start from optional_new_start");
19928 }
19929 #endif
19930 }
19931 }
19932 }
19933
19934 force_start:
19935
19936
19937
19938 if (w->force_start)
19939 {
19940
19941 int new_vpos = -1;
19942
19943 w->force_start = false;
19944
19945
19946
19947
19948 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19949 w->vscroll = 0;
19950
19951 w->preserve_vscroll_p = false;
19952 w->window_end_valid = false;
19953
19954
19955 if (!buffer_unchanged_p)
19956 w->base_line_number = 0;
19957
19958
19959
19960
19961
19962
19963
19964
19965 if (!update_mode_line
19966 || ! NILP (Vwindow_scroll_functions))
19967 {
19968 update_mode_line = true;
19969 w->update_mode_line = true;
19970 startp = run_window_scroll_functions (window, startp);
19971 }
19972
19973 if (CHARPOS (startp) < BEGV)
19974 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19975 else if (CHARPOS (startp) > ZV)
19976 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19977
19978
19979
19980 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19981 goto ignore_start;
19982
19983
19984
19985
19986
19987
19988 clear_glyph_matrix (w->desired_matrix);
19989 if (!try_window (window, startp, 0))
19990 {
19991 w->force_start = true;
19992 clear_glyph_matrix (w->desired_matrix);
19993 goto need_larger_matrices;
19994 }
19995
19996 if (w->cursor.vpos < 0)
19997 {
19998
19999
20000
20001
20002
20003 struct glyph_row *r = NULL;
20004 Lisp_Object invprop =
20005 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20006 Qnil, NULL);
20007
20008 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
20009 {
20010 ptrdiff_t alt_pt;
20011 Lisp_Object invprop_end =
20012 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20013 Qnil, Qnil);
20014
20015 if (FIXNATP (invprop_end))
20016 alt_pt = XFIXNAT (invprop_end);
20017 else
20018 alt_pt = ZV;
20019 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
20020 NULL, 0);
20021 }
20022 if (r)
20023 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
20024 else
20025 new_vpos = window_box_height (w) / 2;
20026 }
20027
20028 if (!cursor_row_fully_visible_p (w, false, false, false))
20029 {
20030
20031
20032 new_vpos = window_box_height (w);
20033
20034
20035
20036
20037
20038
20039 if (new_vpos >= w->cursor.y)
20040 {
20041 w->cursor.vpos = -1;
20042 clear_glyph_matrix (w->desired_matrix);
20043 goto try_to_scroll;
20044 }
20045 }
20046 else if (w->cursor.vpos >= 0)
20047 {
20048
20049
20050
20051 int pixel_margin = margin * frame_line_height;
20052 bool tab_line = window_wants_tab_line (w);
20053 bool header_line = window_wants_header_line (w);
20054
20055
20056
20057
20058
20059 if (w->cursor.vpos < margin + tab_line + header_line)
20060 {
20061 w->cursor.vpos = -1;
20062 clear_glyph_matrix (w->desired_matrix);
20063 goto try_to_scroll;
20064 }
20065 else
20066 {
20067 int window_height = window_box_height (w);
20068
20069 if (tab_line)
20070 window_height += CURRENT_TAB_LINE_HEIGHT (w);
20071 if (header_line)
20072 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
20073 if (w->cursor.y >= window_height - pixel_margin)
20074 {
20075 w->cursor.vpos = -1;
20076 clear_glyph_matrix (w->desired_matrix);
20077 goto try_to_scroll;
20078 }
20079 }
20080 }
20081
20082
20083
20084 if (new_vpos >= 0)
20085 {
20086 struct glyph_row *row;
20087
20088 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
20089 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
20090 && !row->ends_at_zv_p)
20091 ++row;
20092
20093 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
20094 MATRIX_ROW_START_BYTEPOS (row));
20095
20096 if (w != XWINDOW (selected_window))
20097 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
20098 else if (current_buffer == old)
20099 SET_TEXT_POS (lpoint, PT, PT_BYTE);
20100
20101 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
20102
20103
20104
20105
20106
20107
20108
20109 w->redisplay = false;
20110 XBUFFER (w->contents)->text->redisplay = false;
20111 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
20112
20113 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
20114 || ((EQ (Vdisplay_line_numbers, Qrelative)
20115 || EQ (Vdisplay_line_numbers, Qvisual))
20116 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
20117 {
20118
20119
20120
20121
20122 clear_glyph_matrix (w->desired_matrix);
20123 if (!try_window (window, startp, 0))
20124 goto need_larger_matrices;
20125 }
20126 }
20127 if (w->cursor.vpos < 0
20128 || !cursor_row_fully_visible_p (w, false, false, false))
20129 {
20130 clear_glyph_matrix (w->desired_matrix);
20131 goto try_to_scroll;
20132 }
20133
20134 #ifdef GLYPH_DEBUG
20135 debug_method_add (w, "forced window start");
20136 #endif
20137 goto done;
20138 }
20139
20140 ignore_start:
20141
20142
20143
20144
20145 if (current_matrix_up_to_date_p
20146 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
20147 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
20148 {
20149 switch (rc)
20150 {
20151 case CURSOR_MOVEMENT_SUCCESS:
20152 used_current_matrix_p = true;
20153 goto done;
20154
20155 case CURSOR_MOVEMENT_MUST_SCROLL:
20156 goto try_to_scroll;
20157
20158 default:
20159 emacs_abort ();
20160 }
20161 }
20162
20163
20164
20165 else if (w->start_at_line_beg
20166 && ((CHARPOS (startp) > BEGV
20167 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
20168 || (CHARPOS (startp) >= BEGV
20169 && CHARPOS (startp) <= ZV
20170 && !window_start_acceptable_p (window, CHARPOS (startp)))))
20171 {
20172 #ifdef GLYPH_DEBUG
20173 debug_method_add (w, "recenter 1");
20174 #endif
20175 goto recenter;
20176 }
20177
20178
20179
20180
20181 else if ((tem = try_window_id (w)) != 0)
20182 {
20183 #ifdef GLYPH_DEBUG
20184 debug_method_add (w, "try_window_id %d", tem);
20185 #endif
20186
20187 if (f->fonts_changed)
20188 goto need_larger_matrices;
20189 if (tem > 0)
20190 goto done;
20191
20192
20193
20194 }
20195 else if (CHARPOS (startp) >= BEGV
20196 && CHARPOS (startp) <= ZV
20197 && PT >= CHARPOS (startp)
20198 && (CHARPOS (startp) < ZV
20199
20200 || CHARPOS (startp) == BEGV
20201 || !window_outdated (w)))
20202 {
20203 int d1, d2, d5, d6;
20204 int rtop, rbot;
20205
20206
20207
20208
20209
20210
20211
20212
20213
20214
20215 if (!w->start_at_line_beg
20216 && NILP (track_mouse)
20217 && CHARPOS (startp) > BEGV
20218 && CHARPOS (startp) > BEG + beg_unchanged
20219 && CHARPOS (startp) <= Z - end_unchanged
20220
20221
20222
20223
20224
20225 && XMARKER (w->start)->buffer == current_buffer
20226 && compute_window_start_on_continuation_line (w)
20227
20228
20229
20230
20231
20232
20233 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20234
20235
20236 && (rtop != 0) == (rbot != 0))
20237 {
20238 w->force_start = true;
20239 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20240 #ifdef GLYPH_DEBUG
20241 debug_method_add (w, "recomputed window start in continuation line");
20242 #endif
20243 goto force_start;
20244 }
20245
20246
20247
20248
20249 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20250 {
20251 #ifdef GLYPH_DEBUG
20252 debug_method_add (w, "recenter 2");
20253 #endif
20254 goto recenter;
20255 }
20256
20257 #ifdef GLYPH_DEBUG
20258 debug_method_add (w, "same window start");
20259 #endif
20260
20261
20262
20263 if (!current_matrix_up_to_date_p
20264
20265
20266
20267 || !NILP (Vwindow_scroll_functions)
20268 || MINI_WINDOW_P (w)
20269 || !(used_current_matrix_p
20270 = try_window_reusing_current_matrix (w)))
20271 {
20272 IF_DEBUG (debug_method_add (w, "1"));
20273 clear_glyph_matrix (w->desired_matrix);
20274 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20275
20276
20277
20278 goto try_to_scroll;
20279 }
20280
20281 if (f->fonts_changed)
20282 goto need_larger_matrices;
20283
20284 if (w->cursor.vpos >= 0)
20285 {
20286 if (!just_this_one_p
20287 || current_buffer->clip_changed
20288 || BEG_UNCHANGED < CHARPOS (startp))
20289
20290 w->base_line_number = 0;
20291
20292 if (!cursor_row_fully_visible_p (w, true, false, false))
20293 {
20294 clear_glyph_matrix (w->desired_matrix);
20295 last_line_misfit = true;
20296 }
20297
20298 else
20299 goto done;
20300 }
20301 else
20302 clear_glyph_matrix (w->desired_matrix);
20303 }
20304
20305 try_to_scroll:
20306
20307
20308 if (!update_mode_line)
20309 {
20310 update_mode_line = true;
20311 w->update_mode_line = true;
20312 }
20313
20314
20315 if ((0 < scroll_conservatively
20316
20317
20318
20319
20320 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20321 || 0 < emacs_scroll_step
20322 || temp_scroll_step
20323 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20324 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20325 && CHARPOS (startp) >= BEGV
20326 && CHARPOS (startp) <= ZV)
20327 {
20328
20329
20330 int ss = try_scrolling (window, just_this_one_p,
20331 ((scroll_minibuffer_conservatively
20332 && MINI_WINDOW_P (w))
20333 ? SCROLL_LIMIT + 1
20334 : scroll_conservatively),
20335 emacs_scroll_step,
20336 temp_scroll_step, last_line_misfit);
20337 switch (ss)
20338 {
20339 case SCROLLING_SUCCESS:
20340 goto done;
20341
20342 case SCROLLING_NEED_LARGER_MATRICES:
20343 goto need_larger_matrices;
20344
20345 case SCROLLING_FAILED:
20346 break;
20347
20348 default:
20349 emacs_abort ();
20350 }
20351 }
20352
20353
20354
20355
20356 recenter:
20357
20358 #ifdef GLYPH_DEBUG
20359 debug_method_add (w, "recenter");
20360 #endif
20361
20362
20363 if (!buffer_unchanged_p)
20364 w->base_line_number = 0;
20365
20366
20367 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20368 it.current_y = it.last_visible_y;
20369 if (centering_position < 0)
20370 {
20371 ptrdiff_t margin_pos = CHARPOS (startp);
20372 Lisp_Object aggressive;
20373 bool scrolling_up;
20374
20375
20376
20377 if (margin
20378
20379
20380
20381
20382
20383
20384 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20385 {
20386 struct it it1;
20387 void *it1data = NULL;
20388
20389 SAVE_IT (it1, it, it1data);
20390 start_display (&it1, w, startp);
20391 move_it_vertically (&it1, margin * frame_line_height);
20392 margin_pos = IT_CHARPOS (it1);
20393 RESTORE_IT (&it, &it, it1data);
20394 }
20395 scrolling_up = PT > margin_pos;
20396 aggressive =
20397 scrolling_up
20398 ? BVAR (current_buffer, scroll_up_aggressively)
20399 : BVAR (current_buffer, scroll_down_aggressively);
20400
20401 if (!MINI_WINDOW_P (w)
20402 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20403 {
20404 int pt_offset = 0;
20405
20406
20407
20408 if (!scroll_conservatively && NUMBERP (aggressive))
20409 {
20410 double float_amount = XFLOATINT (aggressive);
20411
20412 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20413 if (pt_offset == 0 && float_amount > 0)
20414 pt_offset = 1;
20415 if (pt_offset && margin > 0)
20416 margin -= 1;
20417 }
20418
20419
20420
20421 if (scrolling_up)
20422 {
20423 centering_position = it.last_visible_y;
20424 if (pt_offset)
20425 centering_position -= pt_offset;
20426 centering_position -=
20427 (frame_line_height * (1 + margin + last_line_misfit)
20428 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20429
20430
20431 if (centering_position < margin * frame_line_height)
20432 centering_position = margin * frame_line_height;
20433 }
20434 else
20435 centering_position = margin * frame_line_height + pt_offset;
20436 }
20437 else
20438
20439
20440 centering_position = window_box_height (w) / 2;
20441 }
20442 if (current_buffer->long_line_optimizations_p
20443 && it.line_wrap == TRUNCATE)
20444 {
20445
20446
20447
20448 int nlines = centering_position / frame_line_height;
20449
20450 while (nlines-- && IT_CHARPOS (it) > BEGV)
20451 back_to_previous_visible_line_start (&it);
20452 reseat_1 (&it, it.current.pos, true);
20453 }
20454 else
20455 move_it_vertically_backward (&it, centering_position);
20456
20457 eassert (IT_CHARPOS (it) >= BEGV);
20458
20459
20460
20461
20462
20463
20464 if (it.current_y <= 0)
20465 {
20466 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20467 move_it_vertically_backward (&it, 0);
20468 it.current_y = 0;
20469 }
20470
20471 it.current_x = it.hpos = 0;
20472
20473
20474
20475
20476 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20477
20478
20479 startp = run_window_scroll_functions (window, it.current.pos);
20480
20481
20482
20483
20484 itdata = bidi_shelve_cache ();
20485
20486
20487 use_desired_matrix = false;
20488 if (!current_matrix_up_to_date_p
20489 || windows_or_buffers_changed
20490 || f->cursor_type_changed
20491
20492
20493 || !NILP (Vwindow_scroll_functions)
20494 || !just_this_one_p
20495 || MINI_WINDOW_P (w)
20496 || !(used_current_matrix_p
20497 = try_window_reusing_current_matrix (w)))
20498 use_desired_matrix = (try_window (window, startp, 0) == 1);
20499
20500 bidi_unshelve_cache (itdata, false);
20501
20502
20503
20504
20505 if (f->fonts_changed)
20506 goto need_larger_matrices;
20507
20508
20509
20510
20511
20512
20513 if (w->cursor.vpos < 0)
20514 {
20515 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20516 {
20517 clear_glyph_matrix (w->desired_matrix);
20518 move_it_by_lines (&it, 1);
20519 try_window (window, it.current.pos, 0);
20520 }
20521 else if (PT < IT_CHARPOS (it))
20522 {
20523 clear_glyph_matrix (w->desired_matrix);
20524 move_it_by_lines (&it, -1);
20525 try_window (window, it.current.pos, 0);
20526 }
20527 else if (scroll_conservatively > SCROLL_LIMIT
20528 && (it.method == GET_FROM_STRING
20529 || overlay_touches_p (IT_CHARPOS (it)))
20530 && IT_CHARPOS (it) < ZV)
20531 {
20532
20533
20534
20535
20536
20537
20538
20539
20540 ptrdiff_t pos0 = IT_CHARPOS (it);
20541
20542 clear_glyph_matrix (w->desired_matrix);
20543 do {
20544 move_it_by_lines (&it, 1);
20545 } while (IT_CHARPOS (it) == pos0);
20546 try_window (window, it.current.pos, 0);
20547 }
20548 else
20549 {
20550
20551 }
20552 }
20553
20554
20555
20556
20557
20558
20559 if (w->cursor.vpos < 0)
20560 {
20561
20562
20563
20564
20565 struct glyph_matrix *matrix =
20566 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20567
20568 struct glyph_row *row =
20569 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20570
20571
20572
20573
20574
20575
20576
20577 if (!row)
20578 {
20579 Lisp_Object val =
20580 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20581 Qnil, NULL);
20582
20583 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20584 {
20585 ptrdiff_t alt_pos;
20586 Lisp_Object invis_end =
20587 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20588 Qnil, Qnil);
20589
20590 if (FIXNATP (invis_end))
20591 alt_pos = XFIXNAT (invis_end);
20592 else
20593 alt_pos = ZV;
20594 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20595 }
20596 }
20597
20598
20599
20600 if (!row)
20601 {
20602 row = matrix->rows;
20603
20604 if (row->tab_line_p)
20605 ++row;
20606 if (row->mode_line_p)
20607 ++row;
20608 }
20609 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20610 }
20611
20612 if (!cursor_row_fully_visible_p (w, false, false, false))
20613 {
20614
20615 if (w->vscroll)
20616 {
20617 w->vscroll = 0;
20618 clear_glyph_matrix (w->desired_matrix);
20619 goto recenter;
20620 }
20621
20622
20623
20624
20625
20626 if (scroll_conservatively > SCROLL_LIMIT)
20627 {
20628 int window_total_lines
20629 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20630 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20631
20632 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20633 clear_glyph_matrix (w->desired_matrix);
20634 if (1 == try_window (window, it.current.pos,
20635 TRY_WINDOW_CHECK_MARGINS))
20636 goto done;
20637 }
20638
20639
20640
20641
20642 if (centering_position == 0)
20643 goto done;
20644
20645 clear_glyph_matrix (w->desired_matrix);
20646 centering_position = 0;
20647 goto recenter;
20648 }
20649
20650 done:
20651
20652 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20653 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20654 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20655
20656
20657 if ((update_mode_line
20658
20659
20660
20661
20662 || (!just_this_one_p
20663 && !FRAME_WINDOW_P (f)
20664 && !WINDOW_FULL_WIDTH_P (w))
20665
20666 || w->base_line_pos > 0
20667
20668 || (w->column_number_displayed != -1
20669 && (w->column_number_displayed != current_column ())))
20670
20671 && (window_wants_mode_line (w)
20672 || window_wants_header_line (w)
20673 || window_wants_tab_line (w)))
20674 {
20675 specpdl_ref count1 = SPECPDL_INDEX ();
20676
20677 specbind (Qinhibit_quit, Qt);
20678 display_mode_lines (w);
20679 unbind_to (count1, Qnil);
20680
20681
20682
20683 if (window_wants_mode_line (w)
20684 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20685 {
20686 f->fonts_changed = true;
20687 w->mode_line_height = -1;
20688 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20689 = DESIRED_MODE_LINE_HEIGHT (w);
20690 }
20691
20692
20693
20694 if (window_wants_tab_line (w)
20695 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20696 {
20697 f->fonts_changed = true;
20698 w->tab_line_height = -1;
20699 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20700 = DESIRED_TAB_LINE_HEIGHT (w);
20701 }
20702
20703
20704
20705 if (window_wants_header_line (w)
20706 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20707 {
20708 f->fonts_changed = true;
20709 w->header_line_height = -1;
20710 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20711 = DESIRED_HEADER_LINE_HEIGHT (w);
20712 }
20713
20714 if (f->fonts_changed)
20715 goto need_larger_matrices;
20716 }
20717
20718 if (!line_number_displayed && w->base_line_pos != -1)
20719 {
20720 w->base_line_pos = 0;
20721 w->base_line_number = 0;
20722 }
20723
20724 finish_menu_bars:
20725
20726
20727
20728 if (update_mode_line
20729 && EQ (FRAME_SELECTED_WINDOW (f), window))
20730 {
20731 bool redisplay_menu_p;
20732
20733 if (FRAME_WINDOW_P (f))
20734 {
20735 #ifdef HAVE_EXT_MENU_BAR
20736 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20737 #else
20738 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20739 #endif
20740 }
20741 else
20742 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20743
20744 if (redisplay_menu_p)
20745 display_menu_bar (w);
20746
20747 #ifdef HAVE_WINDOW_SYSTEM
20748 if (FRAME_WINDOW_P (f))
20749 {
20750 if (WINDOWP (f->tab_bar_window)
20751 && (FRAME_TAB_BAR_LINES (f) > 0
20752 || !NILP (Vauto_resize_tab_bars))
20753 && redisplay_tab_bar (f))
20754 ignore_mouse_drag_p = true;
20755
20756 #ifdef HAVE_EXT_TOOL_BAR
20757 if (FRAME_EXTERNAL_TOOL_BAR (f))
20758 update_frame_tool_bar (f);
20759 #else
20760 if (WINDOWP (f->tool_bar_window)
20761 && (FRAME_TOOL_BAR_LINES (f) > 0
20762 || !NILP (Vauto_resize_tool_bars))
20763 && redisplay_tool_bar (f))
20764 ignore_mouse_drag_p = true;
20765 #endif
20766 }
20767 else
20768 {
20769 if ((FRAME_TAB_BAR_LINES (f) > 0))
20770 display_tab_bar (w);
20771 }
20772
20773 gui_consider_frame_title (w->frame);
20774 #else
20775 if ((FRAME_TAB_BAR_LINES (f) > 0))
20776 display_tab_bar (w);
20777 #endif
20778 }
20779
20780 #ifdef HAVE_WINDOW_SYSTEM
20781 if (FRAME_WINDOW_P (f)
20782 && update_window_fringes (w, (just_this_one_p
20783 || (!used_current_matrix_p && !overlay_arrow_seen)
20784 || w->pseudo_window_p)))
20785 {
20786 update_begin (f);
20787 block_input ();
20788 if (draw_window_fringes (w, true))
20789 {
20790 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20791 gui_draw_right_divider (w);
20792 else
20793 gui_draw_vertical_border (w);
20794 }
20795 unblock_input ();
20796 update_end (f);
20797 }
20798
20799 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20800 gui_draw_bottom_divider (w);
20801 #endif
20802
20803
20804
20805
20806
20807 need_larger_matrices:
20808 ;
20809 finish_scroll_bars:
20810
20811 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20812 {
20813 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20814
20815 set_vertical_scroll_bar (w);
20816
20817 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20818
20819 set_horizontal_scroll_bar (w);
20820
20821
20822
20823 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20824 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20825 }
20826
20827
20828
20829
20830 if (CHARPOS (opoint) < BEGV)
20831 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20832 else if (CHARPOS (opoint) > ZV)
20833 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20834 else
20835 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20836
20837 set_buffer_internal_1 (old);
20838
20839
20840 if (CHARPOS (lpoint) <= ZV)
20841 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20842
20843 unbind_to (count, Qnil);
20844 }
20845
20846
20847
20848
20849
20850
20851
20852
20853
20854
20855
20856
20857
20858
20859
20860
20861
20862
20863
20864
20865 int
20866 try_window (Lisp_Object window, struct text_pos pos, int flags)
20867 {
20868 struct window *w = XWINDOW (window);
20869 struct it it;
20870 struct glyph_row *last_text_row = NULL;
20871 struct frame *f = XFRAME (w->frame);
20872 int cursor_vpos = w->cursor.vpos;
20873
20874
20875 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20876
20877
20878 w->cursor.vpos = -1;
20879 overlay_arrow_seen = false;
20880
20881
20882 start_display (&it, w, pos);
20883 it.glyph_row->reversed_p = false;
20884
20885
20886 while (it.current_y < it.last_visible_y)
20887 {
20888 int last_row_scale = it.w->nrows_scale_factor;
20889 int last_col_scale = it.w->ncols_scale_factor;
20890 if (display_line (&it, cursor_vpos))
20891 last_text_row = it.glyph_row - 1;
20892 if (f->fonts_changed
20893 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20894
20895
20896 && last_row_scale == it.w->nrows_scale_factor
20897 && last_col_scale == it.w->ncols_scale_factor))
20898 return 0;
20899 }
20900
20901
20902
20903 ptrdiff_t it_charpos = IT_CHARPOS (it);
20904
20905
20906
20907
20908 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20909 && w->vscroll == 0
20910 && !MINI_WINDOW_P (w))
20911 {
20912 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20913 int bot_scroll_margin = top_scroll_margin;
20914 if (window_wants_header_line (w))
20915 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20916 if (window_wants_tab_line (w))
20917 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20918 start_display (&it, w, pos);
20919
20920 if ((w->cursor.y >= 0
20921 && w->cursor.y < top_scroll_margin
20922 && CHARPOS (pos) > BEGV)
20923
20924
20925
20926
20927 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20928 - bot_scroll_margin - 1))
20929 {
20930 w->cursor.vpos = -1;
20931 clear_glyph_matrix (w->desired_matrix);
20932 return -1;
20933 }
20934 }
20935
20936
20937 if (w->window_end_pos <= 0 && Z != it_charpos)
20938 w->update_mode_line = true;
20939
20940
20941
20942
20943 if (last_text_row)
20944 {
20945 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20946 adjust_window_ends (w, last_text_row, false);
20947 eassert
20948 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20949 w->window_end_vpos)));
20950 }
20951 else
20952 {
20953 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20954 w->window_end_pos = Z - ZV;
20955 w->window_end_vpos = 0;
20956 }
20957
20958
20959 w->window_end_valid = false;
20960 return 1;
20961 }
20962
20963
20964
20965
20966
20967
20968
20969
20970
20971
20972
20973
20974 static bool
20975 try_window_reusing_current_matrix (struct window *w)
20976 {
20977 struct frame *f = XFRAME (w->frame);
20978 struct glyph_row *bottom_row;
20979 struct it it;
20980 struct run run;
20981 struct text_pos start, new_start;
20982 int nrows_scrolled, i;
20983 struct glyph_row *last_text_row;
20984 struct glyph_row *last_reused_text_row;
20985 struct glyph_row *start_row;
20986 int start_vpos, min_y, max_y;
20987
20988 #ifdef GLYPH_DEBUG
20989 if (inhibit_try_window_reusing)
20990 return false;
20991 #endif
20992
20993 if (
20994 !FRAME_WINDOW_P (f)
20995
20996
20997 || windows_or_buffers_changed
20998 || f->cursor_type_changed
20999
21000
21001
21002 || overlay_arrow_in_current_buffer_p ())
21003 return false;
21004
21005
21006 if (!NILP (Vshow_trailing_whitespace))
21007 return false;
21008
21009
21010 if (window_wants_tab_line (w)
21011 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
21012 return false;
21013
21014
21015 if (window_wants_header_line (w)
21016 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
21017 return false;
21018
21019
21020
21021 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21022 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
21023 return false;
21024
21025
21026 clear_glyph_matrix (w->desired_matrix);
21027
21028
21029
21030
21031 if (!NILP (Vdisplay_line_numbers))
21032 return false;
21033
21034
21035
21036
21037 #ifdef HAVE_NTGUI
21038 if (w32_use_visible_system_caret)
21039 return false;
21040 #endif
21041
21042
21043
21044 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
21045 start = start_row->minpos;
21046 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21047
21048 if (CHARPOS (new_start) <= CHARPOS (start))
21049 {
21050
21051
21052
21053
21054 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
21055 return false;
21056
21057 IF_DEBUG (debug_method_add (w, "twu1"));
21058
21059
21060
21061
21062
21063 start_display (&it, w, new_start);
21064 w->cursor.vpos = -1;
21065 last_text_row = last_reused_text_row = NULL;
21066
21067 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21068 {
21069
21070
21071
21072
21073 while (IT_CHARPOS (it) > CHARPOS (start))
21074 {
21075
21076 start_row++;
21077 start = start_row->minpos;
21078
21079 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
21080 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
21081 || CHARPOS (start) == ZV)
21082 {
21083 clear_glyph_matrix (w->desired_matrix);
21084 return false;
21085 }
21086
21087 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
21088 }
21089
21090
21091 if (IT_CHARPOS (it) == CHARPOS (start)
21092
21093
21094
21095
21096
21097 && it.current.dpvec_index < 0)
21098 break;
21099
21100 it.glyph_row->reversed_p = false;
21101 if (display_line (&it, -1))
21102 last_text_row = it.glyph_row - 1;
21103
21104 }
21105
21106
21107
21108
21109 if (it.current_y < it.last_visible_y)
21110 {
21111 struct glyph_row *row;
21112
21113
21114 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
21115
21116
21117 if (w->cursor.vpos < 0)
21118 {
21119 int dy = it.current_y - start_row->y;
21120
21121 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21122 row = row_containing_pos (w, PT, row, NULL, dy);
21123 if (row)
21124 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
21125 dy, nrows_scrolled);
21126 else
21127 {
21128 clear_glyph_matrix (w->desired_matrix);
21129 return false;
21130 }
21131 }
21132
21133
21134
21135
21136
21137
21138
21139 run.current_y = start_row->y;
21140 run.desired_y = it.current_y;
21141 run.height = it.last_visible_y - it.current_y;
21142
21143 if (run.height > 0 && run.current_y != run.desired_y)
21144 {
21145 #ifdef HAVE_WINDOW_SYSTEM
21146 update_begin (f);
21147 gui_update_window_begin (w);
21148 FRAME_RIF (f)->clear_window_mouse_face (w);
21149 FRAME_RIF (f)->scroll_run_hook (w, &run);
21150 gui_update_window_end (w, false, false);
21151 update_end (f);
21152 #endif
21153 }
21154
21155
21156 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21157 rotate_matrix (w->current_matrix,
21158 start_vpos,
21159 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21160 nrows_scrolled);
21161
21162
21163 for (i = 0; i < nrows_scrolled; ++i)
21164 (start_row + i)->enabled_p = false;
21165
21166
21167 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21168 max_y = it.last_visible_y;
21169 for (row = start_row + nrows_scrolled;
21170 row < bottom_row;
21171 ++row)
21172 {
21173 row->y = it.current_y;
21174 row->visible_height = row->height;
21175
21176 if (row->y < min_y)
21177 row->visible_height -= min_y - row->y;
21178 if (row->y + row->height > max_y)
21179 row->visible_height -= row->y + row->height - max_y;
21180 if (row->fringe_bitmap_periodic_p)
21181 row->redraw_fringe_bitmaps_p = true;
21182
21183 it.current_y += row->height;
21184
21185 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21186 last_reused_text_row = row;
21187 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21188 break;
21189 }
21190
21191
21192
21193 for (++row; row < bottom_row; ++row)
21194 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21195 }
21196
21197
21198
21199
21200
21201 if (last_reused_text_row)
21202 adjust_window_ends (w, last_reused_text_row, true);
21203 else if (last_text_row)
21204 adjust_window_ends (w, last_text_row, false);
21205 else
21206 {
21207
21208 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21209 w->window_end_pos = Z - ZV;
21210 w->window_end_vpos = 0;
21211 }
21212 w->window_end_valid = false;
21213
21214
21215 w->desired_matrix->no_scrolling_p = true;
21216
21217 #ifdef GLYPH_DEBUG
21218 debug_method_add (w, "try_window_reusing_current_matrix 1");
21219 #endif
21220 return true;
21221 }
21222 else if (CHARPOS (new_start) > CHARPOS (start))
21223 {
21224 struct glyph_row *pt_row, *row;
21225 struct glyph_row *first_reusable_row;
21226 struct glyph_row *first_row_to_display;
21227 int dy;
21228 int yb = window_text_bottom_y (w);
21229
21230
21231
21232 first_reusable_row = start_row;
21233 while (first_reusable_row->enabled_p
21234 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21235 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21236 < CHARPOS (new_start)))
21237 ++first_reusable_row;
21238
21239
21240 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21241 || !first_reusable_row->enabled_p
21242 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21243 != CHARPOS (new_start)))
21244 return false;
21245
21246
21247
21248
21249
21250 pt_row = NULL;
21251 for (first_row_to_display = first_reusable_row;
21252 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21253 ++first_row_to_display)
21254 {
21255 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21256 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21257 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21258 && first_row_to_display->ends_at_zv_p
21259 && pt_row == NULL)))
21260 pt_row = first_row_to_display;
21261 }
21262
21263 if (first_row_to_display->y >= yb)
21264 return false;
21265
21266
21267 init_to_row_start (&it, w, first_row_to_display);
21268
21269 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21270 - start_vpos);
21271 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21272 - nrows_scrolled);
21273 it.current_y = (first_row_to_display->y - first_reusable_row->y
21274 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21275
21276
21277
21278
21279 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21280 if (pt_row == NULL)
21281 w->cursor.vpos = -1;
21282 last_text_row = NULL;
21283 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21284 if (display_line (&it, w->cursor.vpos))
21285 last_text_row = it.glyph_row - 1;
21286
21287
21288
21289 if (pt_row)
21290 {
21291 w->cursor.vpos -= nrows_scrolled;
21292 w->cursor.y -= first_reusable_row->y - start_row->y;
21293 }
21294
21295
21296
21297
21298
21299 if (w->cursor.vpos < 0)
21300 {
21301 clear_glyph_matrix (w->desired_matrix);
21302 return false;
21303 }
21304
21305
21306 run.current_y = first_reusable_row->y;
21307 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21308 run.height = it.last_visible_y - run.current_y;
21309 dy = run.current_y - run.desired_y;
21310
21311 if (run.height)
21312 {
21313 #ifdef HAVE_WINDOW_SYSTEM
21314 update_begin (f);
21315 gui_update_window_begin (w);
21316 FRAME_RIF (f)->clear_window_mouse_face (w);
21317 FRAME_RIF (f)->scroll_run_hook (w, &run);
21318 gui_update_window_end (w, false, false);
21319 update_end (f);
21320 #endif
21321 }
21322
21323
21324 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21325 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21326 max_y = it.last_visible_y;
21327 for (row = first_reusable_row; row < first_row_to_display; ++row)
21328 {
21329 row->y -= dy;
21330 row->visible_height = row->height;
21331 if (row->y < min_y)
21332 row->visible_height -= min_y - row->y;
21333 if (row->y + row->height > max_y)
21334 row->visible_height -= row->y + row->height - max_y;
21335 if (row->fringe_bitmap_periodic_p)
21336 row->redraw_fringe_bitmaps_p = true;
21337 }
21338
21339
21340 eassert (nrows_scrolled > 0);
21341 rotate_matrix (w->current_matrix,
21342 start_vpos,
21343 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21344 -nrows_scrolled);
21345
21346
21347 for (row -= nrows_scrolled; row < bottom_row; ++row)
21348 row->enabled_p = false;
21349
21350
21351
21352 if (pt_row)
21353 {
21354 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21355 row < bottom_row
21356 && PT >= MATRIX_ROW_END_CHARPOS (row)
21357 && !row->ends_at_zv_p;
21358 row++)
21359 {
21360 w->cursor.vpos++;
21361 w->cursor.y = row->y;
21362 }
21363 if (row < bottom_row)
21364 {
21365
21366
21367
21368
21369 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21370 {
21371 if (!set_cursor_from_row (w, row, w->current_matrix,
21372 0, 0, 0, 0))
21373 {
21374 clear_glyph_matrix (w->desired_matrix);
21375 return false;
21376 }
21377 }
21378 else
21379 {
21380 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21381 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21382
21383 for (; glyph < end
21384 && (!BUFFERP (glyph->object)
21385 || glyph->charpos < PT);
21386 glyph++)
21387 {
21388 w->cursor.hpos++;
21389 w->cursor.x += glyph->pixel_width;
21390 }
21391 }
21392 }
21393 }
21394
21395
21396
21397
21398 if (last_text_row)
21399 adjust_window_ends (w, last_text_row, false);
21400 else
21401 w->window_end_vpos -= nrows_scrolled;
21402
21403 w->window_end_valid = false;
21404 w->desired_matrix->no_scrolling_p = true;
21405
21406 #ifdef GLYPH_DEBUG
21407 debug_method_add (w, "try_window_reusing_current_matrix 2");
21408 #endif
21409 return true;
21410 }
21411
21412 return false;
21413 }
21414
21415
21416
21417
21418
21419
21420
21421 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21422 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21423 ptrdiff_t *, ptrdiff_t *);
21424 static struct glyph_row *
21425 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21426 struct glyph_row *);
21427
21428
21429
21430
21431
21432
21433
21434 static struct glyph_row *
21435 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21436 struct glyph_row *start)
21437 {
21438 struct glyph_row *row, *row_found;
21439
21440
21441
21442
21443 row_found = NULL;
21444 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21445 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21446 {
21447 eassert (row->enabled_p);
21448 row_found = row;
21449 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21450 break;
21451 ++row;
21452 }
21453
21454 return row_found;
21455 }
21456
21457
21458
21459
21460
21461
21462
21463
21464
21465
21466
21467
21468 static struct glyph_row *
21469 find_last_unchanged_at_beg_row (struct window *w)
21470 {
21471 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21472 struct glyph_row *row;
21473 struct glyph_row *row_found = NULL;
21474 int yb = window_text_bottom_y (w);
21475
21476
21477 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21478 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21479 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21480 ++row)
21481 {
21482 if (
21483
21484 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21485
21486
21487 && !row->ends_at_zv_p
21488
21489
21490
21491 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21492 && (row->continued_p
21493 || row->exact_window_width_line_p))
21494
21495
21496
21497
21498
21499
21500
21501 && CHARPOS (row->end.pos) <= ZV)
21502 row_found = row;
21503
21504
21505 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21506 break;
21507 }
21508
21509 return row_found;
21510 }
21511
21512
21513
21514
21515
21516
21517
21518
21519
21520
21521
21522
21523
21524
21525 static struct glyph_row *
21526 find_first_unchanged_at_end_row (struct window *w,
21527 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21528 {
21529 struct glyph_row *row;
21530 struct glyph_row *row_found = NULL;
21531
21532 *delta = *delta_bytes = 0;
21533
21534
21535
21536 eassert (w->window_end_valid);
21537
21538
21539
21540
21541 if (w->window_end_pos >= END_UNCHANGED)
21542 return NULL;
21543
21544
21545 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21546
21547
21548 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21549 {
21550
21551
21552
21553
21554
21555 ptrdiff_t Z_old =
21556 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21557 ptrdiff_t Z_BYTE_old =
21558 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21559 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21560 struct glyph_row *first_text_row
21561 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21562
21563 *delta = Z - Z_old;
21564 *delta_bytes = Z_BYTE - Z_BYTE_old;
21565
21566
21567
21568
21569
21570
21571
21572 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21573 last_unchanged_pos_old = last_unchanged_pos - *delta;
21574
21575
21576
21577 for (; row > first_text_row; --row)
21578 {
21579
21580
21581 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21582 break;
21583
21584 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21585 row_found = row;
21586 }
21587 }
21588
21589 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21590
21591 return row_found;
21592 }
21593
21594
21595
21596
21597
21598
21599
21600
21601 static void
21602 sync_frame_with_window_matrix_rows (struct window *w)
21603 {
21604 struct frame *f = XFRAME (w->frame);
21605 struct glyph_row *window_row, *window_row_end, *frame_row;
21606
21607
21608
21609 eassert (BUFFERP (w->contents));
21610 eassert (WINDOW_FULL_WIDTH_P (w));
21611 eassert (!FRAME_WINDOW_P (f));
21612
21613
21614
21615
21616
21617 window_row = w->current_matrix->rows;
21618 window_row_end = window_row + w->current_matrix->nrows;
21619 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21620 while (window_row < window_row_end)
21621 {
21622 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21623 struct glyph *end = window_row->glyphs[LAST_AREA];
21624
21625 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21626 frame_row->glyphs[TEXT_AREA] = start;
21627 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21628 frame_row->glyphs[LAST_AREA] = end;
21629
21630
21631
21632 if (!window_row->enabled_p)
21633 frame_row->enabled_p = false;
21634
21635 ++window_row, ++frame_row;
21636 }
21637 }
21638
21639
21640
21641
21642
21643
21644
21645 struct glyph_row *
21646 row_containing_pos (struct window *w, ptrdiff_t charpos,
21647 struct glyph_row *start, struct glyph_row *end, int dy)
21648 {
21649 struct glyph_row *row = start;
21650 struct glyph_row *best_row = NULL;
21651 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21652 int last_y;
21653
21654
21655 if (row->tab_line_p)
21656 ++row;
21657 if (row->mode_line_p)
21658 ++row;
21659
21660 if ((end && row >= end) || !row->enabled_p)
21661 return NULL;
21662
21663 last_y = window_text_bottom_y (w) - dy;
21664
21665 while (true)
21666 {
21667
21668 if ((end && row >= end) || !row->enabled_p)
21669 return NULL;
21670
21671
21672
21673 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21674 return NULL;
21675
21676
21677 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21678 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21679
21680
21681
21682
21683 && !row_for_charpos_p (row, charpos)))
21684 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21685 {
21686 struct glyph *g;
21687
21688 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21689 || (!best_row && !row->continued_p))
21690 return row;
21691
21692
21693
21694
21695 for (g = row->glyphs[TEXT_AREA];
21696 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21697 g++)
21698 {
21699 if (!STRINGP (g->object))
21700 {
21701 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21702 {
21703 mindif = eabs (g->charpos - charpos);
21704 best_row = row;
21705
21706 if (mindif == 0)
21707 return best_row;
21708 }
21709 }
21710 }
21711 }
21712 else if (best_row && !row->continued_p)
21713 return best_row;
21714 ++row;
21715 }
21716 }
21717
21718
21719
21720
21721
21722
21723
21724
21725
21726
21727
21728
21729
21730
21731
21732
21733
21734
21735
21736
21737
21738
21739
21740
21741
21742
21743
21744
21745
21746
21747
21748
21749
21750
21751
21752
21753
21754
21755
21756
21757
21758
21759
21760
21761 static int
21762 try_window_id (struct window *w)
21763 {
21764 struct frame *f = XFRAME (w->frame);
21765 struct glyph_matrix *current_matrix = w->current_matrix;
21766 struct glyph_matrix *desired_matrix = w->desired_matrix;
21767 struct glyph_row *last_unchanged_at_beg_row;
21768 struct glyph_row *first_unchanged_at_end_row;
21769 struct glyph_row *row;
21770 struct glyph_row *bottom_row;
21771 int bottom_vpos;
21772 struct it it;
21773 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21774 int dvpos, dy;
21775 struct text_pos start_pos;
21776 struct run run;
21777 int first_unchanged_at_end_vpos = 0;
21778 struct glyph_row *last_text_row, *last_text_row_at_end;
21779 struct text_pos start;
21780 ptrdiff_t first_changed_charpos, last_changed_charpos;
21781
21782 #ifdef GLYPH_DEBUG
21783 if (inhibit_try_window_id)
21784 return 0;
21785 #endif
21786
21787
21788 #if false
21789 #define GIVE_UP(X) \
21790 do { \
21791 redisplay_trace ("try_window_id give up %d\n", X); \
21792 return 0; \
21793 } while (false)
21794 #else
21795 #define GIVE_UP(X) return 0
21796 #endif
21797
21798 SET_TEXT_POS_FROM_MARKER (start, w->start);
21799
21800
21801
21802 if (MINI_WINDOW_P (w))
21803 GIVE_UP (1);
21804
21805
21806 if (windows_or_buffers_changed || f->cursor_type_changed)
21807 GIVE_UP (2);
21808
21809
21810
21811
21812 if (w->last_overlay_modified != OVERLAY_MODIFF)
21813 GIVE_UP (200);
21814
21815
21816
21817
21818
21819 if (current_buffer->clip_changed
21820 || current_buffer->prevent_redisplay_optimizations_p)
21821 GIVE_UP (3);
21822
21823
21824 if (!FRAME_WINDOW_P (f)
21825 && (!FRAME_LINE_INS_DEL_OK (f)
21826 || !WINDOW_FULL_WIDTH_P (w)))
21827 GIVE_UP (4);
21828
21829
21830 if (PT < CHARPOS (start))
21831 GIVE_UP (5);
21832
21833
21834 if (w->last_modified == 0)
21835 GIVE_UP (6);
21836
21837
21838 if (w->hscroll != 0)
21839 GIVE_UP (7);
21840
21841
21842 if (!w->window_end_valid)
21843 GIVE_UP (8);
21844
21845
21846 if (!NILP (Vshow_trailing_whitespace))
21847 GIVE_UP (11);
21848
21849
21850
21851 if (overlay_arrows_changed_p (false))
21852 GIVE_UP (12);
21853
21854
21855
21856
21857
21858 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21859 GIVE_UP (21);
21860
21861
21862
21863
21864
21865
21866
21867
21868
21869 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21870 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21871 GIVE_UP (22);
21872
21873
21874
21875 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21876 GIVE_UP (23);
21877
21878
21879
21880 if (EQ (Vdisplay_line_numbers, Qrelative)
21881 || EQ (Vdisplay_line_numbers, Qvisual)
21882 || (!NILP (Vdisplay_line_numbers)
21883 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21884 Qline_number_current_line,
21885 w->frame))))
21886 GIVE_UP (24);
21887
21888
21889
21890
21891 if (composition_break_at_point)
21892 GIVE_UP (27);
21893
21894
21895
21896
21897
21898 if (MODIFF > SAVE_MODIFF
21899
21900 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21901 {
21902 if (GPT - BEG < BEG_UNCHANGED)
21903 BEG_UNCHANGED = GPT - BEG;
21904 if (Z - GPT < END_UNCHANGED)
21905 END_UNCHANGED = Z - GPT;
21906 }
21907
21908
21909 first_changed_charpos = BEG + BEG_UNCHANGED;
21910 last_changed_charpos = Z - END_UNCHANGED;
21911
21912
21913
21914
21915
21916
21917 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21918 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21919 && ((last_changed_charpos < CHARPOS (start)
21920 && CHARPOS (start) == BEGV)
21921 || (last_changed_charpos < CHARPOS (start) - 1
21922 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21923 {
21924 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21925 struct glyph_row *r0;
21926
21927
21928
21929 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21930 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21931 Z_delta = Z - Z_old;
21932 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21933
21934
21935
21936
21937 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21938 GIVE_UP (13);
21939
21940
21941
21942
21943 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21944 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21945 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21946
21947 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21948 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21949 {
21950
21951 if (Z_delta || Z_delta_bytes)
21952 {
21953 struct glyph_row *r1
21954 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21955 increment_matrix_positions (w->current_matrix,
21956 MATRIX_ROW_VPOS (r0, current_matrix),
21957 MATRIX_ROW_VPOS (r1, current_matrix),
21958 Z_delta, Z_delta_bytes);
21959 }
21960
21961
21962 row = row_containing_pos (w, PT, r0, NULL, 0);
21963 if (row)
21964 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21965 return 1;
21966 }
21967 }
21968
21969
21970
21971
21972
21973 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21974
21975
21976 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21977 || first_changed_charpos == last_changed_charpos))
21978 {
21979 struct glyph_row *r0;
21980
21981
21982
21983
21984 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21985 GIVE_UP (14);
21986
21987
21988
21989
21990 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21991 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21992
21993 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21994 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21995 {
21996
21997
21998 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
21999 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22000
22001
22002 row = row_containing_pos (w, PT, r0, NULL, 0);
22003 if (row)
22004 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
22005 return 2;
22006 }
22007 }
22008
22009
22010
22011
22012
22013
22014
22015
22016 if (CHARPOS (start) >= first_changed_charpos
22017 && CHARPOS (start) <= last_changed_charpos)
22018 GIVE_UP (15);
22019
22020
22021
22022
22023
22024 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
22025 if (!TEXT_POS_EQUAL_P (start, row->minpos))
22026 GIVE_UP (16);
22027
22028
22029
22030 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
22031 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
22032 GIVE_UP (20);
22033
22034
22035
22036
22037
22038 #ifdef HAVE_NTGUI
22039 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
22040 GIVE_UP (25);
22041 #endif
22042
22043
22044
22045
22046
22047
22048
22049 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
22050 if (last_unchanged_at_beg_row)
22051 {
22052
22053
22054
22055
22056 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
22057 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
22058 && last_unchanged_at_beg_row > w->current_matrix->rows)
22059 --last_unchanged_at_beg_row;
22060
22061 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
22062 GIVE_UP (17);
22063
22064 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
22065 GIVE_UP (18);
22066
22067
22068
22069 if (it.sp > 1
22070 && it.method == GET_FROM_IMAGE && it.image_id == -1)
22071 GIVE_UP (26);
22072 start_pos = it.current.pos;
22073
22074
22075
22076
22077 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
22078 current_matrix);
22079 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22080 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
22081
22082 eassert (it.hpos == 0 && it.current_x == 0);
22083 }
22084 else
22085 {
22086
22087
22088 start_display (&it, w, start);
22089 it.vpos = it.first_vpos;
22090 start_pos = it.current.pos;
22091 }
22092
22093
22094
22095
22096
22097
22098
22099 first_unchanged_at_end_row
22100 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
22101 IF_DEBUG (debug_delta = delta);
22102 IF_DEBUG (debug_delta_bytes = delta_bytes);
22103
22104
22105
22106
22107
22108
22109 stop_pos = 0;
22110 if (first_unchanged_at_end_row)
22111 {
22112 eassert (last_unchanged_at_beg_row == NULL
22113 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
22114
22115
22116
22117
22118
22119 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
22120 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22121 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22122 < it.last_visible_y))
22123 ++first_unchanged_at_end_row;
22124
22125 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
22126 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
22127 >= it.last_visible_y))
22128 first_unchanged_at_end_row = NULL;
22129 else
22130 {
22131 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
22132 + delta);
22133 first_unchanged_at_end_vpos
22134 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
22135 eassert (stop_pos >= Z - END_UNCHANGED);
22136 }
22137 }
22138 else if (last_unchanged_at_beg_row == NULL)
22139 GIVE_UP (19);
22140
22141
22142 #ifdef GLYPH_DEBUG
22143
22144
22145
22146
22147 eassert (first_unchanged_at_end_row == NULL
22148 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22149
22150 debug_last_unchanged_at_beg_vpos
22151 = (last_unchanged_at_beg_row
22152 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
22153 : -1);
22154 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
22155
22156 #endif
22157
22158
22159
22160
22161
22162 w->cursor.vpos = -1;
22163 last_text_row = NULL;
22164 overlay_arrow_seen = false;
22165 if (it.current_y < it.last_visible_y
22166 && !f->fonts_changed
22167 && (first_unchanged_at_end_row == NULL
22168 || IT_CHARPOS (it) < stop_pos))
22169 it.glyph_row->reversed_p = false;
22170 while (it.current_y < it.last_visible_y
22171 && !f->fonts_changed
22172 && (first_unchanged_at_end_row == NULL
22173 || IT_CHARPOS (it) < stop_pos))
22174 {
22175 if (display_line (&it, -1))
22176 last_text_row = it.glyph_row - 1;
22177 }
22178
22179 if (f->fonts_changed)
22180 return -1;
22181
22182
22183
22184
22185
22186
22187
22188
22189
22190
22191
22192 if (!w->window_end_valid)
22193 {
22194 clear_glyph_matrix (w->desired_matrix);
22195 return -1;
22196 }
22197
22198
22199
22200
22201 if (first_unchanged_at_end_row
22202
22203
22204 && it.current_y < it.last_visible_y)
22205 {
22206 dvpos = (it.vpos
22207 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22208 current_matrix));
22209 dy = it.current_y - first_unchanged_at_end_row->y;
22210 run.current_y = first_unchanged_at_end_row->y;
22211 run.desired_y = run.current_y + dy;
22212 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22213 }
22214 else
22215 {
22216 delta = delta_bytes = dvpos = dy
22217 = run.current_y = run.desired_y = run.height = 0;
22218 first_unchanged_at_end_row = NULL;
22219 }
22220 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22221
22222
22223
22224
22225
22226
22227
22228
22229
22230
22231 if (w->cursor.vpos < 0)
22232 {
22233
22234 if (PT < CHARPOS (start_pos)
22235 && last_unchanged_at_beg_row)
22236 {
22237 row = row_containing_pos (w, PT,
22238 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22239 last_unchanged_at_beg_row + 1, 0);
22240 if (row)
22241 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22242 }
22243
22244
22245 else if (first_unchanged_at_end_row)
22246 {
22247 row = row_containing_pos (w, PT - delta,
22248 first_unchanged_at_end_row, NULL, 0);
22249 if (row)
22250 set_cursor_from_row (w, row, w->current_matrix, delta,
22251 delta_bytes, dy, dvpos);
22252 }
22253
22254
22255 if (w->cursor.vpos < 0)
22256 {
22257 clear_glyph_matrix (w->desired_matrix);
22258 return -1;
22259 }
22260 }
22261
22262
22263 {
22264 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22265 int bot_scroll_margin = top_scroll_margin;
22266 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22267
22268 if (window_wants_header_line (w))
22269 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22270 if (window_wants_tab_line (w))
22271 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22272
22273 if ((w->cursor.y < top_scroll_margin
22274 && CHARPOS (start) > BEGV)
22275
22276
22277 || (w->cursor.y
22278 + (cursor_row_fully_visible_p (w, false, true, true)
22279 ? 1
22280 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22281 {
22282 w->cursor.vpos = -1;
22283 clear_glyph_matrix (w->desired_matrix);
22284 return -1;
22285 }
22286 }
22287
22288
22289
22290
22291 if (dy && run.height)
22292 {
22293 update_begin (f);
22294
22295 if (FRAME_WINDOW_P (f))
22296 {
22297 #ifdef HAVE_WINDOW_SYSTEM
22298 gui_update_window_begin (w);
22299 FRAME_RIF (f)->clear_window_mouse_face (w);
22300 FRAME_RIF (f)->scroll_run_hook (w, &run);
22301 gui_update_window_end (w, false, false);
22302 #endif
22303 }
22304 else
22305 {
22306
22307
22308 int from_vpos
22309 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22310 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22311 int end = (WINDOW_TOP_EDGE_LINE (w)
22312 + window_wants_tab_line (w)
22313 + window_wants_header_line (w)
22314 + window_internal_height (w));
22315
22316 gui_clear_window_mouse_face (w);
22317
22318
22319 if (dvpos > 0)
22320 {
22321
22322
22323 set_terminal_window (f, end);
22324
22325
22326
22327 if (!FRAME_SCROLL_REGION_OK (f))
22328 ins_del_lines (f, end - dvpos, -dvpos);
22329
22330
22331
22332 ins_del_lines (f, from, dvpos);
22333 }
22334 else if (dvpos < 0)
22335 {
22336
22337
22338 set_terminal_window (f, end);
22339
22340
22341
22342
22343
22344 ins_del_lines (f, from + dvpos, dvpos);
22345
22346
22347
22348 if (!FRAME_SCROLL_REGION_OK (f))
22349 ins_del_lines (f, end + dvpos, -dvpos);
22350 }
22351
22352 set_terminal_window (f, 0);
22353 }
22354
22355 update_end (f);
22356 }
22357
22358
22359
22360
22361 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22362 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22363 if (dvpos < 0)
22364 {
22365 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22366 bottom_vpos, dvpos);
22367 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22368 bottom_vpos);
22369 }
22370 else if (dvpos > 0)
22371 {
22372 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22373 bottom_vpos, dvpos);
22374 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22375 first_unchanged_at_end_vpos + dvpos);
22376 }
22377
22378
22379
22380 if (!FRAME_WINDOW_P (f))
22381 sync_frame_with_window_matrix_rows (w);
22382
22383
22384 if (delta || delta_bytes)
22385 increment_matrix_positions (current_matrix,
22386 first_unchanged_at_end_vpos + dvpos,
22387 bottom_vpos, delta, delta_bytes);
22388
22389
22390 if (dy)
22391 shift_glyph_matrix (w, current_matrix,
22392 first_unchanged_at_end_vpos + dvpos,
22393 bottom_vpos, dy);
22394
22395 if (first_unchanged_at_end_row)
22396 {
22397 first_unchanged_at_end_row += dvpos;
22398 if (first_unchanged_at_end_row->y >= it.last_visible_y
22399 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22400 first_unchanged_at_end_row = NULL;
22401 }
22402
22403
22404
22405 last_text_row_at_end = NULL;
22406 if (dy < 0)
22407 {
22408
22409
22410
22411
22412
22413 int last_vpos = w->window_end_vpos + dvpos;
22414 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22415
22416
22417 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22418
22419
22420
22421
22422 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22423 {
22424 init_to_row_start (&it, w, last_row);
22425 it.vpos = last_vpos;
22426 it.current_y = last_row->y;
22427 }
22428 else
22429 {
22430 init_to_row_end (&it, w, last_row);
22431 it.vpos = 1 + last_vpos;
22432 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22433 ++last_row;
22434 }
22435
22436
22437
22438 it.continuation_lines_width = last_row->continuation_lines_width;
22439 it.hpos = it.current_x = 0;
22440
22441
22442 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22443 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22444 {
22445
22446
22447
22448
22449 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22450 if (display_line (&it, w->cursor.vpos))
22451 last_text_row_at_end = it.glyph_row - 1;
22452 }
22453 }
22454
22455
22456 if (first_unchanged_at_end_row && !last_text_row_at_end)
22457 {
22458
22459
22460
22461
22462 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22463 row = find_last_row_displaying_text (w->current_matrix, &it,
22464 first_unchanged_at_end_row);
22465 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22466 adjust_window_ends (w, row, true);
22467 eassert (w->window_end_bytepos >= 0);
22468 IF_DEBUG (debug_method_add (w, "A"));
22469 }
22470 else if (last_text_row_at_end)
22471 {
22472 adjust_window_ends (w, last_text_row_at_end, false);
22473 eassert (w->window_end_bytepos >= 0);
22474 IF_DEBUG (debug_method_add (w, "B"));
22475 }
22476 else if (last_text_row)
22477 {
22478
22479
22480
22481 adjust_window_ends (w, last_text_row, false);
22482 eassert (w->window_end_bytepos >= 0);
22483 }
22484 else if (first_unchanged_at_end_row == NULL
22485 && last_text_row == NULL
22486 && last_text_row_at_end == NULL)
22487 {
22488
22489
22490 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22491 int vpos = w->window_end_vpos;
22492 struct glyph_row *current_row = current_matrix->rows + vpos;
22493 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22494
22495 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22496 {
22497 eassert (first_vpos <= vpos);
22498 if (desired_row->enabled_p)
22499 {
22500 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22501 row = desired_row;
22502 }
22503 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22504 row = current_row;
22505 }
22506
22507 w->window_end_vpos = vpos + 1;
22508 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22509 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22510 eassert (w->window_end_bytepos >= 0);
22511 IF_DEBUG (debug_method_add (w, "C"));
22512 }
22513 else
22514 emacs_abort ();
22515
22516 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22517 debug_end_vpos = w->window_end_vpos));
22518
22519
22520 w->window_end_valid = false;
22521 w->desired_matrix->no_scrolling_p = true;
22522 return 3;
22523
22524 #undef GIVE_UP
22525 }
22526
22527
22528
22529
22530
22531
22532
22533 #ifdef GLYPH_DEBUG
22534
22535 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22536 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22537 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22538
22539
22540
22541
22542
22543
22544
22545
22546 void
22547 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22548 {
22549 int i;
22550 for (i = 0; i < matrix->nrows; ++i)
22551 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22552 }
22553
22554
22555
22556
22557
22558 void
22559 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22560 {
22561 if (glyph->type == CHAR_GLYPH
22562 || glyph->type == GLYPHLESS_GLYPH)
22563 {
22564 fprintf (stderr,
22565 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22566 glyph - row->glyphs[TEXT_AREA],
22567 (glyph->type == CHAR_GLYPH
22568 ? 'C'
22569 : 'G'),
22570 glyph->charpos,
22571 (BUFFERP (glyph->object)
22572 ? 'B'
22573 : (STRINGP (glyph->object)
22574 ? 'S'
22575 : (NILP (glyph->object)
22576 ? '0'
22577 : '-'))),
22578 glyph->pixel_width,
22579 glyph->u.ch,
22580 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22581 ? (int) glyph->u.ch
22582 : '.'),
22583 glyph->face_id,
22584 glyph->left_box_line_p,
22585 glyph->right_box_line_p);
22586 }
22587 else if (glyph->type == STRETCH_GLYPH)
22588 {
22589 fprintf (stderr,
22590 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22591 glyph - row->glyphs[TEXT_AREA],
22592 'S',
22593 glyph->charpos,
22594 (BUFFERP (glyph->object)
22595 ? 'B'
22596 : (STRINGP (glyph->object)
22597 ? 'S'
22598 : (NILP (glyph->object)
22599 ? '0'
22600 : '-'))),
22601 glyph->pixel_width,
22602 0u,
22603 ' ',
22604 glyph->face_id,
22605 glyph->left_box_line_p,
22606 glyph->right_box_line_p);
22607 }
22608 else if (glyph->type == IMAGE_GLYPH)
22609 {
22610 fprintf (stderr,
22611 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22612 glyph - row->glyphs[TEXT_AREA],
22613 'I',
22614 glyph->charpos,
22615 (BUFFERP (glyph->object)
22616 ? 'B'
22617 : (STRINGP (glyph->object)
22618 ? 'S'
22619 : (NILP (glyph->object)
22620 ? '0'
22621 : '-'))),
22622 glyph->pixel_width,
22623 (unsigned int) glyph->u.img_id,
22624 '.',
22625 glyph->face_id,
22626 glyph->left_box_line_p,
22627 glyph->right_box_line_p);
22628 }
22629 else if (glyph->type == COMPOSITE_GLYPH)
22630 {
22631 fprintf (stderr,
22632 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22633 glyph - row->glyphs[TEXT_AREA],
22634 '+',
22635 glyph->charpos,
22636 (BUFFERP (glyph->object)
22637 ? 'B'
22638 : (STRINGP (glyph->object)
22639 ? 'S'
22640 : (NILP (glyph->object)
22641 ? '0'
22642 : '-'))),
22643 glyph->pixel_width,
22644 (unsigned int) glyph->u.cmp.id);
22645 if (glyph->u.cmp.automatic)
22646 fprintf (stderr,
22647 "[%d-%d]",
22648 glyph->slice.cmp.from, glyph->slice.cmp.to);
22649 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22650 glyph->face_id,
22651 glyph->left_box_line_p,
22652 glyph->right_box_line_p);
22653 }
22654 else if (glyph->type == XWIDGET_GLYPH)
22655 {
22656 #ifndef HAVE_XWIDGETS
22657 eassume (false);
22658 #else
22659 fprintf (stderr,
22660 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22661 glyph - row->glyphs[TEXT_AREA],
22662 'X',
22663 glyph->charpos,
22664 (BUFFERP (glyph->object)
22665 ? 'B'
22666 : (STRINGP (glyph->object)
22667 ? 'S'
22668 : '-')),
22669 glyph->pixel_width,
22670 glyph->u.xwidget,
22671 '.',
22672 glyph->face_id,
22673 glyph->left_box_line_p,
22674 glyph->right_box_line_p);
22675 #endif
22676 }
22677 }
22678
22679
22680
22681
22682
22683
22684
22685 void
22686 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22687 {
22688 if (glyphs != 1)
22689 {
22690 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22691 "==============================================================================\n"),
22692 stderr);
22693 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22694 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22695 vpos,
22696 MATRIX_ROW_START_CHARPOS (row),
22697 MATRIX_ROW_END_CHARPOS (row),
22698 row->used[TEXT_AREA],
22699 row->contains_overlapping_glyphs_p,
22700 row->enabled_p,
22701 row->truncated_on_left_p,
22702 row->truncated_on_right_p,
22703 row->continued_p,
22704 MATRIX_ROW_CONTINUATION_LINE_P (row),
22705 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22706 row->ends_at_zv_p,
22707 row->fill_line_p,
22708 row->ends_in_middle_of_char_p,
22709 row->starts_in_middle_of_char_p,
22710 row->mouse_face_p,
22711 row->x,
22712 row->y,
22713 row->pixel_width,
22714 row->height,
22715 row->visible_height,
22716 row->ascent,
22717 row->phys_ascent);
22718
22719 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22720 row->end.overlay_string_index,
22721 row->continuation_lines_width);
22722 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22723 CHARPOS (row->start.string_pos),
22724 CHARPOS (row->end.string_pos));
22725 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22726 row->end.dpvec_index);
22727 }
22728
22729 if (glyphs > 1)
22730 {
22731 int area;
22732
22733 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22734 {
22735 struct glyph *glyph = row->glyphs[area];
22736 struct glyph *glyph_end = glyph + row->used[area];
22737
22738
22739 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22740 ++glyph_end;
22741
22742 if (glyph < glyph_end)
22743 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22744 stderr);
22745
22746 for (; glyph < glyph_end; ++glyph)
22747 dump_glyph (row, glyph, area);
22748 }
22749 }
22750 else if (glyphs == 1)
22751 {
22752 int area;
22753 char s[SHRT_MAX + 4];
22754
22755 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22756 {
22757 int i;
22758
22759 for (i = 0; i < row->used[area]; ++i)
22760 {
22761 struct glyph *glyph = row->glyphs[area] + i;
22762 if (i == row->used[area] - 1
22763 && area == TEXT_AREA
22764 && NILP (glyph->object)
22765 && glyph->type == CHAR_GLYPH
22766 && glyph->u.ch == ' ')
22767 {
22768 strcpy (&s[i], "[\\n]");
22769 i += 4;
22770 }
22771 else if (glyph->type == CHAR_GLYPH
22772 && glyph->u.ch < 0x80
22773 && glyph->u.ch >= ' ')
22774 s[i] = glyph->u.ch;
22775 else
22776 s[i] = '.';
22777 }
22778
22779 s[i] = '\0';
22780 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22781 }
22782 }
22783 }
22784
22785
22786 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22787 Sdump_glyph_matrix, 0, 1, "p",
22788 doc:
22789
22790
22791
22792
22793
22794 )
22795 (Lisp_Object glyphs)
22796 {
22797 struct window *w = XWINDOW (selected_window);
22798 struct buffer *buffer = XBUFFER (w->contents);
22799
22800 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22801 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22802 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22803 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22804 fputs ("=============================================\n", stderr);
22805 dump_glyph_matrix (w->current_matrix,
22806 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22807 return Qnil;
22808 }
22809
22810
22811 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22812 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22813 )
22814 (void)
22815 {
22816 struct frame *f = XFRAME (selected_frame);
22817
22818 if (f->current_matrix)
22819 dump_glyph_matrix (f->current_matrix, 1);
22820 else
22821 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22822 return Qnil;
22823 }
22824
22825
22826 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22827 doc:
22828
22829
22830
22831
22832 )
22833 (Lisp_Object row, Lisp_Object glyphs)
22834 {
22835 struct glyph_matrix *matrix;
22836 EMACS_INT vpos;
22837
22838 if (NILP (row))
22839 {
22840 int d1, d2, d3, d4, d5, ypos;
22841 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22842 &d1, &d2, &d3, &d4, &d5, &ypos);
22843 if (visible_p)
22844 vpos = ypos;
22845 else
22846 vpos = 0;
22847 }
22848 else
22849 {
22850 CHECK_FIXNUM (row);
22851 vpos = XFIXNUM (row);
22852 }
22853 matrix = XWINDOW (selected_window)->current_matrix;
22854 if (vpos >= 0 && vpos < matrix->nrows)
22855 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22856 vpos,
22857 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22858 return Qnil;
22859 }
22860
22861
22862 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22863 doc:
22864
22865
22866
22867
22868
22869
22870 )
22871 (Lisp_Object row, Lisp_Object glyphs)
22872 {
22873 #if defined (HAVE_WINDOW_SYSTEM)
22874 struct frame *sf = SELECTED_FRAME ();
22875 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22876 ? XWINDOW (sf->tab_bar_window)->current_matrix
22877 : sf->current_matrix;
22878 EMACS_INT vpos;
22879
22880 if (NILP (row))
22881 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22882 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22883 else
22884 {
22885 CHECK_FIXNUM (row);
22886 vpos = XFIXNUM (row);
22887 }
22888 if (vpos >= 0 && vpos < m->nrows)
22889 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22890 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22891 #endif
22892 return Qnil;
22893 }
22894
22895 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22896 doc:
22897
22898
22899
22900
22901
22902
22903 )
22904 (Lisp_Object row, Lisp_Object glyphs)
22905 {
22906 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22907 struct frame *sf = SELECTED_FRAME ();
22908 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22909 EMACS_INT vpos;
22910
22911 if (NILP (row))
22912 vpos = 0;
22913 else
22914 {
22915 CHECK_FIXNUM (row);
22916 vpos = XFIXNUM (row);
22917 }
22918 if (vpos >= 0 && vpos < m->nrows)
22919 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22920 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22921 #endif
22922 return Qnil;
22923 }
22924
22925
22926 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22927 doc:
22928 )
22929 (Lisp_Object arg)
22930 {
22931 if (NILP (arg))
22932 trace_redisplay_p = !trace_redisplay_p;
22933 else
22934 {
22935 arg = Fprefix_numeric_value (arg);
22936 trace_redisplay_p = XFIXNUM (arg) > 0;
22937 }
22938
22939 return Qnil;
22940 }
22941
22942
22943 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22944 doc:
22945 )
22946 (ptrdiff_t nargs, Lisp_Object *args)
22947 {
22948 Lisp_Object s = Fformat (nargs, args);
22949 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22950 return Qnil;
22951 }
22952
22953 #endif
22954
22955
22956
22957
22958
22959
22960
22961
22962
22963
22964
22965 static struct glyph_row *
22966 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22967 {
22968 struct frame *f = XFRAME (WINDOW_FRAME (w));
22969 struct buffer *buffer = XBUFFER (w->contents);
22970 struct buffer *old = current_buffer;
22971 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22972 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22973 const unsigned char *arrow_end = arrow_string + arrow_len;
22974 const unsigned char *p;
22975 struct it it;
22976 bool multibyte_p;
22977 int n_glyphs_before;
22978
22979 set_buffer_temp (buffer);
22980 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22981 scratch_glyph_row.reversed_p = false;
22982 it.glyph_row->used[TEXT_AREA] = 0;
22983 SET_TEXT_POS (it.position, 0, 0);
22984
22985 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22986 p = arrow_string;
22987 while (p < arrow_end)
22988 {
22989 Lisp_Object face, ilisp;
22990
22991
22992 if (multibyte_p)
22993 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22994 else
22995 {
22996 it.c = it.char_to_display = *p, it.len = 1;
22997 if (! ASCII_CHAR_P (it.c))
22998 it.char_to_display = BYTE8_TO_CHAR (it.c);
22999 }
23000 p += it.len;
23001
23002
23003 ilisp = make_fixnum (char_num++);
23004 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
23005 it.face_id = compute_char_face (f, it.char_to_display, face);
23006
23007
23008 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
23009 SET_TEXT_POS (it.position, -1, -1);
23010 PRODUCE_GLYPHS (&it);
23011
23012
23013
23014 if (it.current_x > it.last_visible_x)
23015 {
23016 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
23017 break;
23018 }
23019 }
23020
23021 set_buffer_temp (old);
23022 return it.glyph_row;
23023 }
23024
23025
23026
23027
23028
23029 static void
23030 insert_left_trunc_glyphs (struct it *it)
23031 {
23032 struct it truncate_it;
23033 struct glyph *from, *end, *to, *toend;
23034
23035 eassert (!FRAME_WINDOW_P (it->f)
23036 || (!it->glyph_row->reversed_p
23037 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23038 || (it->glyph_row->reversed_p
23039 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
23040
23041
23042 truncate_it = *it;
23043 truncate_it.current_x = 0;
23044 truncate_it.face_id = DEFAULT_FACE_ID;
23045 truncate_it.glyph_row = &scratch_glyph_row;
23046 truncate_it.area = TEXT_AREA;
23047 truncate_it.glyph_row->used[TEXT_AREA] = 0;
23048 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
23049 truncate_it.object = Qnil;
23050 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
23051
23052
23053 if (!it->glyph_row->reversed_p)
23054 {
23055 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23056
23057 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23058 end = from + tused;
23059 to = it->glyph_row->glyphs[TEXT_AREA];
23060 toend = to + it->glyph_row->used[TEXT_AREA];
23061 if (FRAME_WINDOW_P (it->f))
23062 {
23063
23064
23065
23066
23067
23068
23069
23070 int w = 0;
23071 struct glyph *g = to;
23072 short used;
23073
23074
23075
23076
23077
23078
23079 it->glyph_row->x = 0;
23080 while (g < toend && w < it->truncation_pixel_width)
23081 {
23082 w += g->pixel_width;
23083 ++g;
23084 }
23085 if (g - to - tused > 0)
23086 {
23087 memmove (to + tused, g, (toend - g) * sizeof(*g));
23088 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
23089 }
23090 used = it->glyph_row->used[TEXT_AREA];
23091 if (it->glyph_row->truncated_on_right_p
23092 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
23093 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
23094 == STRETCH_GLYPH)
23095 {
23096 int extra = w - it->truncation_pixel_width;
23097
23098 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
23099 }
23100 }
23101
23102 while (from < end)
23103 *to++ = *from++;
23104
23105
23106 if (!FRAME_WINDOW_P (it->f))
23107 {
23108 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
23109 {
23110 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
23111 while (from < end)
23112 *to++ = *from++;
23113 }
23114 }
23115
23116 if (to > toend)
23117 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
23118 }
23119 else
23120 {
23121 short tused = truncate_it.glyph_row->used[TEXT_AREA];
23122
23123
23124
23125 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
23126 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23127 toend = it->glyph_row->glyphs[TEXT_AREA];
23128 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
23129 if (FRAME_WINDOW_P (it->f))
23130 {
23131 int w = 0;
23132 struct glyph *g = to;
23133
23134 while (g >= toend && w < it->truncation_pixel_width)
23135 {
23136 w += g->pixel_width;
23137 --g;
23138 }
23139 if (to - g - tused > 0)
23140 to = g + tused;
23141 if (it->glyph_row->truncated_on_right_p
23142 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
23143 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
23144 {
23145 int extra = w - it->truncation_pixel_width;
23146
23147 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
23148 }
23149 }
23150
23151 while (from >= end && to >= toend)
23152 *to-- = *from--;
23153 if (!FRAME_WINDOW_P (it->f))
23154 {
23155 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
23156 {
23157 from =
23158 truncate_it.glyph_row->glyphs[TEXT_AREA]
23159 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
23160 while (from >= end && to >= toend)
23161 *to-- = *from--;
23162 }
23163 }
23164 if (from >= end)
23165 {
23166
23167
23168 int move_by = from - end + 1;
23169 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
23170 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
23171
23172 for ( ; g >= g0; g--)
23173 g[move_by] = *g;
23174 while (from >= end)
23175 *to-- = *from--;
23176 it->glyph_row->used[TEXT_AREA] += move_by;
23177 }
23178 }
23179 }
23180
23181
23182 unsigned
23183 row_hash (struct glyph_row *row)
23184 {
23185 int area, k;
23186 unsigned hashval = 0;
23187
23188 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23189 for (k = 0; k < row->used[area]; ++k)
23190 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23191 + row->glyphs[area][k].u.val
23192 + row->glyphs[area][k].face_id
23193 + row->glyphs[area][k].padding_p
23194 + (row->glyphs[area][k].type << 2));
23195
23196 return hashval;
23197 }
23198
23199
23200
23201
23202
23203
23204
23205
23206
23207
23208
23209
23210
23211
23212
23213
23214
23215
23216 static void
23217 compute_line_metrics (struct it *it)
23218 {
23219 struct glyph_row *row = it->glyph_row;
23220
23221 if (FRAME_WINDOW_P (it->f))
23222 {
23223 int i, min_y, max_y;
23224
23225
23226
23227
23228 if (row->height == 0)
23229 {
23230 if (it->max_ascent + it->max_descent == 0)
23231 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23232 row->ascent = it->max_ascent;
23233 row->height = it->max_ascent + it->max_descent;
23234 row->phys_ascent = it->max_phys_ascent;
23235 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23236 row->extra_line_spacing = it->max_extra_line_spacing;
23237 }
23238
23239
23240 row->pixel_width = row->x;
23241 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23242 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23243
23244 eassert (row->pixel_width >= 0);
23245 eassert (row->ascent >= 0 && row->height > 0);
23246
23247 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23248 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23249
23250
23251
23252
23253 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23254 && row->phys_ascent > row->ascent)
23255 {
23256 row->height += row->phys_ascent - row->ascent;
23257 row->ascent = row->phys_ascent;
23258 }
23259
23260
23261 row->visible_height = row->height;
23262
23263 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23264 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23265
23266 if (row->y < min_y)
23267 row->visible_height -= min_y - row->y;
23268 if (row->y + row->height > max_y)
23269 row->visible_height -= row->y + row->height - max_y;
23270 }
23271 else
23272 {
23273 row->pixel_width = row->used[TEXT_AREA];
23274 if (row->continued_p)
23275 row->pixel_width -= it->continuation_pixel_width;
23276 else if (row->truncated_on_right_p)
23277 row->pixel_width -= it->truncation_pixel_width;
23278 row->ascent = row->phys_ascent = 0;
23279 row->height = row->phys_height = row->visible_height = 1;
23280 row->extra_line_spacing = 0;
23281 }
23282
23283
23284 row->hash = row_hash (row);
23285
23286 it->max_ascent = it->max_descent = 0;
23287 it->max_phys_ascent = it->max_phys_descent = 0;
23288 }
23289
23290
23291 static void
23292 clear_position (struct it *it)
23293 {
23294 it->position.charpos = 0;
23295 it->position.bytepos = 0;
23296 }
23297
23298
23299
23300
23301
23302
23303
23304
23305
23306
23307
23308
23309
23310 static bool
23311 append_space_for_newline (struct it *it, bool default_face_p)
23312 {
23313 int n = it->glyph_row->used[TEXT_AREA];
23314
23315 if (it->glyph_row->glyphs[TEXT_AREA] + n
23316 < it->glyph_row->glyphs[1 + TEXT_AREA])
23317 {
23318
23319
23320
23321
23322 enum display_element_type saved_what = it->what;
23323 int saved_c = it->c, saved_len = it->len;
23324 int saved_char_to_display = it->char_to_display;
23325 int saved_x = it->current_x;
23326 const int saved_face_id = it->face_id;
23327 bool saved_box_end = it->end_of_box_run_p;
23328 struct text_pos saved_pos = it->position;
23329 Lisp_Object saved_object = it->object;
23330 struct face *face;
23331
23332 it->what = IT_CHARACTER;
23333 clear_position (it);
23334 it->object = Qnil;
23335 it->len = 1;
23336
23337 int char_width = 1;
23338
23339 if (default_face_p
23340 #ifdef HAVE_WINDOW_SYSTEM
23341 || FRAME_WINDOW_P (it->f)
23342 #endif
23343 )
23344 {
23345 const int local_default_face_id =
23346 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23347
23348 #ifdef HAVE_WINDOW_SYSTEM
23349 if (FRAME_WINDOW_P (it->f))
23350 {
23351 struct face *default_face
23352 = FACE_FROM_ID (it->f, local_default_face_id);
23353 struct font *font = (default_face->font
23354 ? default_face->font
23355 : FRAME_FONT (it->f));
23356 char_width = (font->average_width
23357 ? font->average_width
23358 : font->space_width);
23359 }
23360 #endif
23361 if (default_face_p)
23362 it->face_id = local_default_face_id;
23363 }
23364
23365
23366
23367
23368 const int indicator_column =
23369 fill_column_indicator_column (it, char_width);
23370 int saved_end_of_box_run = it->end_of_box_run_p;
23371 bool should_keep_end_of_box_run = false;
23372
23373 if (it->current_x == indicator_column)
23374 {
23375 it->c = it->char_to_display
23376 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23377 it->face_id
23378 = merge_faces (it->w, Qfill_column_indicator,
23379 0, saved_face_id);
23380 face = FACE_FROM_ID (it->f, it->face_id);
23381 }
23382 else
23383 {
23384 it->c = it->char_to_display = ' ';
23385
23386
23387
23388 face = FACE_FROM_ID (it->f, it->face_id);
23389 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23390
23391
23392
23393
23394 if (!(it->glyph_row->reversed_p
23395
23396
23397
23398 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23399 should_keep_end_of_box_run = true;
23400 }
23401 PRODUCE_GLYPHS (it);
23402
23403
23404 if (should_keep_end_of_box_run)
23405 it->end_of_box_run_p = saved_end_of_box_run;
23406 #ifdef HAVE_WINDOW_SYSTEM
23407 if (FRAME_WINDOW_P (it->f))
23408 {
23409
23410
23411
23412 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23413 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23414 if (n == 0)
23415 {
23416 Lisp_Object height, total_height;
23417 int extra_line_spacing = it->extra_line_spacing;
23418 int boff = font->baseline_offset;
23419
23420 if (font->vertical_centering)
23421 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23422
23423 it->object = saved_object;
23424 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23425
23426
23427 height = get_it_property (it, Qline_height);
23428 if (CONSP (height)
23429 && CONSP (XCDR (height))
23430 && NILP (XCDR (XCDR (height))))
23431 {
23432 total_height = XCAR (XCDR (height));
23433 height = XCAR (height);
23434 }
23435 else
23436 total_height = Qnil;
23437 height = calc_line_height_property (it, height, font, boff, true);
23438
23439 if (it->override_ascent >= 0)
23440 {
23441 it->ascent = it->override_ascent;
23442 it->descent = it->override_descent;
23443 boff = it->override_boff;
23444 }
23445 if (EQ (height, Qt))
23446 extra_line_spacing = 0;
23447 else
23448 {
23449 Lisp_Object spacing;
23450
23451 it->phys_ascent = it->ascent;
23452 it->phys_descent = it->descent;
23453 if (!NILP (height)
23454 && XFIXNUM (height) > it->ascent + it->descent)
23455 it->ascent = XFIXNUM (height) - it->descent;
23456
23457 if (!NILP (total_height))
23458 spacing = calc_line_height_property (it, total_height, font,
23459 boff, false);
23460 else
23461 {
23462 spacing = get_it_property (it, Qline_spacing);
23463 spacing = calc_line_height_property (it, spacing, font,
23464 boff, false);
23465 }
23466 if (FIXNUMP (spacing))
23467 {
23468 extra_line_spacing = XFIXNUM (spacing);
23469 if (!NILP (total_height))
23470 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23471 }
23472 }
23473 if (extra_line_spacing > 0)
23474 {
23475 it->descent += extra_line_spacing;
23476 if (extra_line_spacing > it->max_extra_line_spacing)
23477 it->max_extra_line_spacing = extra_line_spacing;
23478 }
23479 it->max_ascent = it->ascent;
23480 it->max_descent = it->descent;
23481
23482 it->glyph_row->height = 0;
23483 }
23484
23485 g->ascent = it->max_ascent;
23486 g->descent = it->max_descent;
23487 }
23488 #endif
23489 it->override_ascent = -1;
23490 it->constrain_row_ascent_descent_p = false;
23491 it->current_x = saved_x;
23492 it->object = saved_object;
23493 it->position = saved_pos;
23494 it->what = saved_what;
23495 it->face_id = saved_face_id;
23496 it->len = saved_len;
23497 it->c = saved_c;
23498 it->char_to_display = saved_char_to_display;
23499 it->end_of_box_run_p = saved_box_end;
23500 return true;
23501 }
23502
23503 return false;
23504 }
23505
23506
23507
23508
23509
23510
23511
23512
23513
23514 static void
23515 extend_face_to_end_of_line (struct it *it)
23516 {
23517 struct frame *f = it->f;
23518
23519
23520
23521
23522
23523
23524 if ((it->current_x >= it->last_visible_x
23525 + (!FRAME_WINDOW_P (f)
23526 && it->glyph_row->reversed_p
23527 && !it->glyph_row->continued_p))
23528
23529
23530 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23531 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23532 return;
23533
23534 specpdl_ref count = SPECPDL_INDEX ();
23535
23536
23537
23538
23539 specbind (Qinhibit_quit, Qt);
23540
23541 struct face *default_face =
23542 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23543 if (!default_face)
23544 return;
23545
23546 const int extend_face_id =
23547 (it->face_id == default_face->id || it->s != NULL)
23548 ? it->face_id
23549 : (it->glyph_row->ends_at_zv_p
23550 ? default_face->id
23551 : face_at_pos (it, LFACE_EXTEND_INDEX));
23552 unbind_to (count, Qnil);
23553
23554
23555
23556
23557 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23558 ? it->saved_face_id
23559 : extend_face_id));
23560
23561 if (FRAME_WINDOW_P (f)
23562 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23563 && face->box == FACE_NO_BOX
23564 && face->underline == FACE_NO_UNDERLINE
23565 && !face->overline_p
23566 && !face->strike_through_p
23567 && face->background == FRAME_BACKGROUND_PIXEL (f)
23568 #ifdef HAVE_WINDOW_SYSTEM
23569 && !face->stipple
23570 #endif
23571 && !it->glyph_row->reversed_p
23572 && !display_fill_column_indicator)
23573 return;
23574
23575
23576
23577 it->glyph_row->fill_line_p = true;
23578
23579 const int orig_face_id = it->face_id;
23580
23581
23582
23583
23584
23585 if (!ASCII_CHAR_P (it->c))
23586 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23587
23588
23589 #ifdef HAVE_WINDOW_SYSTEM
23590 if (FRAME_WINDOW_P (f))
23591 {
23592
23593
23594 if (it->glyph_row->used[TEXT_AREA] == 0)
23595 {
23596 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23597 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23598 it->glyph_row->used[TEXT_AREA] = 1;
23599 }
23600
23601
23602 if (!(it->glyph_row->mode_line_p
23603 || (WINDOWP (f->tab_bar_window)
23604 && it->w == XWINDOW (f->tab_bar_window))
23605 #ifndef HAVE_EXT_TOOL_BAR
23606 || (WINDOWP (f->tool_bar_window)
23607 && it->w == XWINDOW (f->tool_bar_window))
23608 #endif
23609 ))
23610 {
23611 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23612 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23613 {
23614 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23615 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23616 default_face->id;
23617 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23618 }
23619 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23620 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23621 {
23622 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23623 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23624 default_face->id;
23625 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23626 }
23627
23628 struct font *font = (default_face->font
23629 ? default_face->font
23630 : FRAME_FONT (f));
23631
23632 const int char_width = (font->average_width
23633 ? font->average_width
23634 : font->space_width);
23635
23636 const int indicator_column =
23637 fill_column_indicator_column (it, char_width);
23638
23639 const char saved_char = it->char_to_display;
23640 const struct text_pos saved_pos = it->position;
23641 const bool saved_avoid_cursor = it->avoid_cursor_p;
23642 const bool saved_box_start = it->start_of_box_run_p;
23643 Lisp_Object save_object = it->object;
23644 const int saved_face_id = it->face_id;
23645
23646 it->face_id = extend_face_id;
23647 it->avoid_cursor_p = true;
23648 it->object = Qnil;
23649
23650 const int stretch_height = it->ascent + it->descent;
23651 const int stretch_ascent =
23652 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23653
23654 if (indicator_column >= 0
23655 && indicator_column > it->current_x
23656 && indicator_column < it->last_visible_x)
23657 {
23658
23659
23660
23661
23662 const int stretch_width =
23663 indicator_column - it->current_x - char_width;
23664
23665 clear_position (it);
23666
23667
23668
23669 if (stretch_width > 0)
23670 {
23671 append_stretch_glyph (it, Qnil, stretch_width,
23672 stretch_height, stretch_ascent);
23673 }
23674
23675
23676
23677 if (it->current_x < indicator_column)
23678 {
23679 const int save_face_id = it->face_id;
23680 const int save_ascent = it->ascent;
23681 const int save_descent = it->descent;
23682 it->char_to_display
23683 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23684 it->face_id
23685 = merge_faces (it->w, Qfill_column_indicator,
23686 0, extend_face_id);
23687 PRODUCE_GLYPHS (it);
23688 it->face_id = save_face_id;
23689 it->ascent = save_ascent;
23690 it->descent = save_descent;
23691 }
23692 }
23693
23694
23695
23696 if (!it->glyph_row->reversed_p)
23697 {
23698 const int stretch_width = it->last_visible_x - it->current_x;
23699
23700 if (stretch_width > 0)
23701 {
23702 clear_position (it);
23703 append_stretch_glyph (it, Qnil, stretch_width,
23704 stretch_height, stretch_ascent);
23705 }
23706 }
23707
23708 it->char_to_display = saved_char;
23709 it->position = saved_pos;
23710 it->avoid_cursor_p = saved_avoid_cursor;
23711 it->start_of_box_run_p = saved_box_start;
23712 it->object = save_object;
23713 it->face_id = saved_face_id;
23714 }
23715 if (it->glyph_row->reversed_p)
23716 {
23717
23718
23719
23720
23721
23722 struct font *font = face->font ? face->font : FRAME_FONT (f);
23723 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23724 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23725 struct glyph *g;
23726 int row_width, stretch_ascent, stretch_width;
23727 struct text_pos saved_pos;
23728 int saved_face_id;
23729 bool saved_avoid_cursor, saved_box_start;
23730
23731 for (row_width = 0, g = row_start; g < row_end; g++)
23732 row_width += g->pixel_width;
23733
23734
23735
23736
23737 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23738 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23739 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23740 stretch_width = window_box_width (it->w, TEXT_AREA);
23741 else
23742 stretch_width = it->last_visible_x - it->first_visible_x;
23743 stretch_width -= row_width;
23744
23745 if (stretch_width > 0)
23746 {
23747 stretch_ascent =
23748 (((it->ascent + it->descent)
23749 * FONT_BASE (font)) / FONT_HEIGHT (font));
23750 saved_pos = it->position;
23751 clear_position (it);
23752 saved_avoid_cursor = it->avoid_cursor_p;
23753 it->avoid_cursor_p = true;
23754 saved_face_id = it->face_id;
23755 saved_box_start = it->start_of_box_run_p;
23756
23757
23758
23759 it->face_id = (it->glyph_row->ends_at_zv_p ?
23760 default_face->id : face->id);
23761
23762 it->start_of_box_run_p = false;
23763 append_stretch_glyph (it, Qnil, stretch_width,
23764 it->ascent + it->descent, stretch_ascent);
23765 it->position = saved_pos;
23766 it->avoid_cursor_p = saved_avoid_cursor;
23767 it->face_id = saved_face_id;
23768 it->start_of_box_run_p = saved_box_start;
23769 }
23770
23771
23772
23773
23774 if (stretch_width < 0)
23775 it->glyph_row->x = stretch_width;
23776 }
23777 it->face_id = orig_face_id;
23778 }
23779 else
23780 #endif
23781 {
23782
23783 int saved_x = it->current_x;
23784 struct text_pos saved_pos = it->position;
23785 Lisp_Object saved_object = it->object;;
23786 enum display_element_type saved_what = it->what;
23787
23788 it->what = IT_CHARACTER;
23789 clear_position (it);
23790 it->object = Qnil;
23791 it->c = it->char_to_display = ' ';
23792 it->len = 1;
23793
23794 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23795 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23796 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23797 && !it->glyph_row->mode_line_p
23798 && face->background != FRAME_BACKGROUND_PIXEL (f))
23799 {
23800 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23801 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23802
23803 for (it->current_x = 0; g < e; g++)
23804 it->current_x += g->pixel_width;
23805
23806 it->area = LEFT_MARGIN_AREA;
23807 it->face_id = default_face->id;
23808 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23809 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23810 && g < it->glyph_row->glyphs[TEXT_AREA])
23811 {
23812 PRODUCE_GLYPHS (it);
23813
23814
23815 it->current_x += it->pixel_width;
23816 g++;
23817 }
23818
23819 it->current_x = saved_x;
23820 it->area = TEXT_AREA;
23821 }
23822
23823
23824
23825
23826 it->face_id = (it->glyph_row->ends_at_zv_p ?
23827 default_face->id : face->id);
23828
23829
23830
23831
23832
23833 it->current_x = it->glyph_row->used[TEXT_AREA];
23834
23835
23836
23837
23838
23839
23840
23841
23842 const int indicator_column =
23843 fill_column_indicator_column (it, 1) - it->first_visible_x;
23844
23845
23846 while (it->current_x <= it->last_visible_x)
23847 {
23848 if (it->current_x != indicator_column)
23849 PRODUCE_GLYPHS (it);
23850 else
23851 {
23852 int saved_face_id = it->face_id;
23853 it->face_id
23854 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23855 it->c = it->char_to_display
23856 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23857
23858 PRODUCE_GLYPHS (it);
23859
23860 it->face_id = saved_face_id;
23861 it->c = it->char_to_display = ' ';
23862 }
23863 }
23864
23865 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23866 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23867 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23868 && !it->glyph_row->mode_line_p
23869 && face->background != FRAME_BACKGROUND_PIXEL (f))
23870 {
23871 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23872 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23873
23874 for ( ; g < e; g++)
23875 it->current_x += g->pixel_width;
23876
23877 it->area = RIGHT_MARGIN_AREA;
23878 it->face_id = default_face->id;
23879 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23880 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23881 && g < it->glyph_row->glyphs[LAST_AREA])
23882 {
23883 PRODUCE_GLYPHS (it);
23884 it->current_x += it->pixel_width;
23885 g++;
23886 }
23887
23888 it->area = TEXT_AREA;
23889 }
23890
23891
23892
23893 it->current_x = saved_x;
23894 it->object = saved_object;
23895 it->position = saved_pos;
23896 it->what = saved_what;
23897 it->face_id = orig_face_id;
23898 }
23899 }
23900
23901
23902
23903
23904
23905 static bool
23906 trailing_whitespace_p (ptrdiff_t charpos)
23907 {
23908 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23909 int c = 0;
23910
23911 while (bytepos < ZV_BYTE
23912 && (c = FETCH_BYTE (bytepos),
23913 c == ' ' || c == '\t'))
23914 ++bytepos;
23915
23916 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23917 {
23918 if (bytepos != PT_BYTE)
23919 return true;
23920 }
23921 return false;
23922 }
23923
23924
23925
23926
23927 static void
23928 highlight_trailing_whitespace (struct it *it)
23929 {
23930 struct glyph_row *row = it->glyph_row;
23931 int used = row->used[TEXT_AREA];
23932
23933 if (used)
23934 {
23935 struct glyph *start = row->glyphs[TEXT_AREA];
23936 struct glyph *glyph = start + used - 1;
23937
23938 if (row->reversed_p)
23939 {
23940
23941
23942 glyph = start;
23943 start = row->glyphs[TEXT_AREA] + used - 1;
23944 }
23945
23946
23947
23948
23949
23950 if (!row->reversed_p)
23951 {
23952 while (glyph >= start
23953 && (glyph->type == CHAR_GLYPH
23954 || glyph->type == STRETCH_GLYPH)
23955 && NILP (glyph->object))
23956 --glyph;
23957 }
23958 else
23959 {
23960 while (glyph <= start
23961 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23962 && NILP (glyph->object))
23963 ++glyph;
23964 }
23965
23966
23967
23968
23969 if ((row->reversed_p ? glyph <= start : glyph >= start)
23970 && BUFFERP (glyph->object)
23971 && (glyph->type == STRETCH_GLYPH
23972 || (glyph->type == CHAR_GLYPH
23973 && glyph->u.ch == ' '))
23974 && trailing_whitespace_p (glyph->charpos))
23975 {
23976 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23977 if (face_id < 0)
23978 return;
23979
23980 if (!row->reversed_p)
23981 {
23982 while (glyph >= start
23983 && BUFFERP (glyph->object)
23984 && (glyph->type == STRETCH_GLYPH
23985 || (glyph->type == CHAR_GLYPH
23986 && glyph->u.ch == ' ')))
23987 (glyph--)->face_id = face_id;
23988 }
23989 else
23990 {
23991 while (glyph <= start
23992 && BUFFERP (glyph->object)
23993 && (glyph->type == STRETCH_GLYPH
23994 || (glyph->type == CHAR_GLYPH
23995 && glyph->u.ch == ' ')))
23996 (glyph++)->face_id = face_id;
23997 }
23998 }
23999 }
24000 }
24001
24002
24003
24004
24005
24006 static bool
24007 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
24008 {
24009 bool result = true;
24010
24011 if (charpos == CHARPOS (row->end.pos)
24012 || charpos == MATRIX_ROW_END_CHARPOS (row))
24013 {
24014
24015
24016
24017
24018
24019
24020
24021
24022 if (CHARPOS (row->end.string_pos) >= 0)
24023 {
24024 if (row->continued_p)
24025 result = true;
24026 else
24027 {
24028
24029 struct glyph *beg = row->glyphs[TEXT_AREA];
24030 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
24031 struct glyph *glyph;
24032
24033 result = false;
24034 for (glyph = end; glyph >= beg; --glyph)
24035 if (STRINGP (glyph->object))
24036 {
24037 Lisp_Object prop
24038 = Fget_char_property (make_fixnum (charpos),
24039 Qdisplay, Qnil);
24040 result =
24041 (!NILP (prop)
24042 && display_prop_string_p (prop, glyph->object));
24043
24044
24045
24046 if (!result)
24047 {
24048 Lisp_Object s = glyph->object;
24049
24050 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
24051 {
24052 ptrdiff_t gpos = glyph->charpos;
24053
24054 if (!NILP (Fget_char_property (make_fixnum (gpos),
24055 Qcursor, s)))
24056 {
24057 result = true;
24058 break;
24059 }
24060 }
24061 }
24062 break;
24063 }
24064 }
24065 }
24066 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
24067 {
24068
24069
24070
24071
24072 if (!row->ends_in_ellipsis_p)
24073 result = row->continued_p;
24074 else
24075
24076
24077
24078
24079 result = false;
24080 }
24081
24082
24083 else
24084 result = row->ends_at_zv_p;
24085 }
24086
24087 return result;
24088 }
24089
24090
24091
24092
24093 static bool
24094 cursor_row_p (struct glyph_row *row)
24095 {
24096 return row_for_charpos_p (row, PT);
24097 }
24098
24099
24100
24101
24102
24103
24104
24105
24106 static bool
24107 push_prefix_prop (struct it *it, Lisp_Object prop)
24108 {
24109 struct text_pos pos =
24110 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
24111
24112 eassert (it->method == GET_FROM_BUFFER
24113 || it->method == GET_FROM_DISPLAY_VECTOR
24114 || it->method == GET_FROM_STRING
24115 || it->method == GET_FROM_IMAGE);
24116
24117
24118
24119
24120
24121 push_it (it, &pos);
24122
24123 if (STRINGP (prop))
24124 {
24125 if (SCHARS (prop) == 0)
24126 {
24127 pop_it (it);
24128 return false;
24129 }
24130
24131 it->string = prop;
24132 it->string_from_prefix_prop_p = true;
24133 it->multibyte_p = STRING_MULTIBYTE (it->string);
24134 it->current.overlay_string_index = -1;
24135 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
24136 it->end_charpos = it->string_nchars = SCHARS (it->string);
24137 it->method = GET_FROM_STRING;
24138 it->stop_charpos = 0;
24139 it->prev_stop = 0;
24140 it->base_level_stop = 0;
24141 it->cmp_it.id = -1;
24142
24143
24144
24145 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
24146 it->paragraph_embedding = it->bidi_it.paragraph_dir;
24147 else
24148 it->paragraph_embedding = L2R;
24149
24150
24151 if (it->bidi_p)
24152 {
24153 it->bidi_it.string.lstring = it->string;
24154 it->bidi_it.string.s = NULL;
24155 it->bidi_it.string.schars = it->end_charpos;
24156 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
24157 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
24158 it->bidi_it.string.unibyte = !it->multibyte_p;
24159 it->bidi_it.w = it->w;
24160 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
24161 }
24162 }
24163 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
24164 {
24165 it->method = GET_FROM_STRETCH;
24166 it->object = prop;
24167 }
24168 #ifdef HAVE_WINDOW_SYSTEM
24169 else if (IMAGEP (prop))
24170 {
24171 it->what = IT_IMAGE;
24172 it->image_id = lookup_image (it->f, prop, it->face_id);
24173 it->method = GET_FROM_IMAGE;
24174 }
24175 #endif
24176 else
24177 {
24178 pop_it (it);
24179 return false;
24180 }
24181
24182 return true;
24183 }
24184
24185
24186
24187 static Lisp_Object
24188 get_it_property (struct it *it, Lisp_Object prop)
24189 {
24190 Lisp_Object position, object = it->object;
24191
24192 if (STRINGP (object))
24193 position = make_fixnum (IT_STRING_CHARPOS (*it));
24194 else if (BUFFERP (object))
24195 {
24196 position = make_fixnum (IT_CHARPOS (*it));
24197 object = it->window;
24198 }
24199 else
24200 return Qnil;
24201
24202 return Fget_char_property (position, prop, object);
24203 }
24204
24205
24206
24207
24208 static Lisp_Object
24209 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24210 {
24211 Lisp_Object prefix = get_it_property (it, prop);
24212
24213
24214
24215 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24216 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24217 it->w->contents);
24218 return prefix;
24219 }
24220
24221
24222
24223 static void
24224 handle_line_prefix (struct it *it)
24225 {
24226 Lisp_Object prefix;
24227
24228 if (it->continuation_lines_width > 0)
24229 {
24230 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24231 if (NILP (prefix))
24232 prefix = Vwrap_prefix;
24233 }
24234 else
24235 {
24236 prefix = get_line_prefix_it_property (it, Qline_prefix);
24237 if (NILP (prefix))
24238 prefix = Vline_prefix;
24239 }
24240 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24241 {
24242
24243
24244
24245 it->line_wrap = TRUNCATE;
24246 it->avoid_cursor_p = true;
24247 }
24248 }
24249
24250
24251
24252
24253
24254
24255
24256 static void
24257 unproduce_glyphs (struct it *it, int n)
24258 {
24259 struct glyph *glyph, *end;
24260
24261 eassert (it->glyph_row);
24262 eassert (it->glyph_row->reversed_p);
24263 eassert (it->area == TEXT_AREA);
24264 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24265
24266 if (n > it->glyph_row->used[TEXT_AREA])
24267 n = it->glyph_row->used[TEXT_AREA];
24268 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24269 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24270 for ( ; glyph < end; glyph++)
24271 glyph[-n] = *glyph;
24272 }
24273
24274
24275
24276 static void
24277 find_row_edges (struct it *it, struct glyph_row *row,
24278 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24279 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24280 {
24281
24282
24283
24284
24285
24286 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24287 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24288 else
24289
24290
24291
24292 row->minpos = row->start.pos;
24293 if (max_pos <= 0)
24294 {
24295 max_pos = CHARPOS (it->current.pos);
24296 max_bpos = BYTEPOS (it->current.pos);
24297 }
24298
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
24311
24312
24313
24314
24315 if (row->ends_at_zv_p)
24316 row->maxpos = it->current.pos;
24317 else if (row->used[TEXT_AREA])
24318 {
24319 bool seen_this_string = false;
24320 struct glyph_row *r1 = row - 1;
24321
24322
24323 if (STRINGP (it->object)
24324
24325 && row > it->w->desired_matrix->rows
24326
24327 && !r1->mode_line_p
24328
24329 && r1->ends_in_newline_from_string_p)
24330 {
24331 struct glyph *start, *end;
24332
24333
24334
24335
24336
24337 if (!r1->reversed_p)
24338 {
24339 start = r1->glyphs[TEXT_AREA];
24340 end = start + r1->used[TEXT_AREA];
24341
24342 while (end > start
24343 && NILP ((end - 1)->object)
24344 && (end - 1)->charpos <= 0)
24345 --end;
24346 if (end > start)
24347 {
24348 if (EQ ((end - 1)->object, it->object))
24349 seen_this_string = true;
24350 }
24351 else
24352
24353
24354
24355
24356
24357 seen_this_string = true;
24358 }
24359 else
24360 {
24361 end = r1->glyphs[TEXT_AREA] - 1;
24362 start = end + r1->used[TEXT_AREA];
24363 while (end < start
24364 && NILP ((end + 1)->object)
24365 && (end + 1)->charpos <= 0)
24366 ++end;
24367 if (end < start)
24368 {
24369 if (EQ ((end + 1)->object, it->object))
24370 seen_this_string = true;
24371 }
24372 else
24373 seen_this_string = true;
24374 }
24375 }
24376
24377
24378
24379 if (row->ends_in_newline_from_string_p && !seen_this_string)
24380 {
24381
24382
24383
24384
24385
24386
24387
24388
24389 if (CHARPOS (row->end.pos) > max_pos)
24390 inc_both (&max_pos, &max_bpos);
24391 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24392 }
24393 else if (CHARPOS (it->eol_pos) > 0)
24394 SET_TEXT_POS (row->maxpos,
24395 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24396 else if (row->continued_p)
24397 {
24398
24399
24400
24401
24402
24403
24404 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24405 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24406 else
24407 {
24408 inc_both (&max_pos, &max_bpos);
24409 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24410 }
24411 }
24412 else if (row->truncated_on_right_p)
24413
24414
24415
24416 row->maxpos = it->current.pos;
24417 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24418
24419 row->maxpos = row->minpos;
24420 else
24421 emacs_abort ();
24422 }
24423 else
24424 row->maxpos = it->current.pos;
24425 }
24426
24427
24428
24429 static ptrdiff_t
24430 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24431 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24432 {
24433 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24434 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24435
24436 ptrdiff_t val;
24437 specpdl_ref pdl_count = SPECPDL_INDEX ();
24438 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24439 labeled_restrictions_remove_in_current_buffer ();
24440 Fwiden ();
24441 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24442 unbind_to (pdl_count, Qnil);
24443 return val;
24444 }
24445
24446
24447
24448 static ptrdiff_t
24449 display_count_lines_visually (struct it *it)
24450 {
24451 struct it tem_it;
24452 ptrdiff_t to;
24453 struct text_pos from;
24454
24455
24456
24457
24458
24459
24460 if (it->lnum_bytepos > 0)
24461 return it->lnum + 1;
24462 else
24463 {
24464 specpdl_ref count = SPECPDL_INDEX ();
24465
24466 if (IT_CHARPOS (*it) <= PT)
24467 {
24468 from = it->current.pos;
24469 to = PT;
24470 }
24471 else
24472 {
24473 SET_TEXT_POS (from, PT, PT_BYTE);
24474 to = IT_CHARPOS (*it);
24475 }
24476
24477
24478
24479 specbind (Qdisplay_line_numbers, Qrelative);
24480 start_display (&tem_it, it->w, from);
24481
24482
24483
24484
24485 move_it_to (&tem_it, to, -1,
24486 tem_it.last_visible_y
24487 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24488 -1, MOVE_TO_POS | MOVE_TO_Y);
24489 unbind_to (count, Qnil);
24490 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24491 }
24492 }
24493
24494
24495
24496
24497 static void
24498 maybe_produce_line_number (struct it *it)
24499 {
24500 ptrdiff_t last_line = it->lnum;
24501 ptrdiff_t start_from, bytepos;
24502 ptrdiff_t this_line;
24503 bool first_time = false;
24504 ptrdiff_t beg_byte;
24505 ptrdiff_t z_byte;
24506 bool line_numbers_wide;
24507 void *itdata = bidi_shelve_cache ();
24508
24509 if (display_line_numbers_offset
24510 && !display_line_numbers_widen
24511 && !EQ (Vdisplay_line_numbers, Qvisual)
24512 && !EQ (Vdisplay_line_numbers, Qrelative))
24513 line_numbers_wide = true;
24514 else
24515 line_numbers_wide = display_line_numbers_widen;
24516
24517 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24518 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24519
24520 if (EQ (Vdisplay_line_numbers, Qvisual))
24521 this_line = display_count_lines_visually (it);
24522 else
24523 {
24524 if (!last_line)
24525 {
24526
24527 if (it->w->base_line_number > 0
24528 && it->w->base_line_pos > 0
24529 && it->w->base_line_pos <= IT_CHARPOS (*it)
24530
24531
24532
24533
24534 && !(line_numbers_wide
24535 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24536 && !current_buffer->clip_changed)
24537 {
24538 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24539 last_line = it->w->base_line_number - 1;
24540 }
24541 else
24542 start_from = beg_byte;
24543 if (!it->lnum_bytepos)
24544 first_time = true;
24545 }
24546 else
24547 start_from = it->lnum_bytepos;
24548
24549
24550
24551
24552 if (!(beg_byte <= start_from && start_from <= z_byte))
24553 {
24554 last_line = 0;
24555 start_from = beg_byte;
24556 }
24557
24558 this_line =
24559 last_line + display_count_lines_logically (start_from,
24560 IT_BYTEPOS (*it),
24561 IT_CHARPOS (*it), &bytepos);
24562 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24563 eassert (bytepos == IT_BYTEPOS (*it));
24564 }
24565
24566
24567 if (this_line != last_line || !it->lnum_bytepos)
24568 {
24569 it->lnum = this_line;
24570 it->lnum_bytepos = IT_BYTEPOS (*it);
24571 }
24572
24573
24574 struct it tem_it;
24575 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24576 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24577 ptrdiff_t lnum_offset = -1;
24578 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24579 int current_lnum_face_id
24580 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24581
24582
24583 bool save_free_realized_faces = inhibit_free_realized_faces;
24584 inhibit_free_realized_faces = true;
24585
24586 if ((EQ (Vdisplay_line_numbers, Qrelative)
24587 || EQ (Vdisplay_line_numbers, Qvisual)
24588 || lnum_face_id != current_lnum_face_id)
24589 && !it->pt_lnum)
24590 {
24591 ptrdiff_t ignored;
24592 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24593 it->pt_lnum =
24594 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24595 PT, &ignored);
24596 else
24597 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24598 &ignored);
24599 }
24600
24601 if (!it->lnum_width)
24602 {
24603 if (FIXNATP (Vdisplay_line_numbers_width))
24604 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24605
24606
24607
24608 ptrdiff_t max_lnum;
24609
24610 if (NILP (Vdisplay_line_numbers_current_absolute)
24611 && (EQ (Vdisplay_line_numbers, Qrelative)
24612 || EQ (Vdisplay_line_numbers, Qvisual)))
24613
24614
24615 max_lnum = it->w->desired_matrix->nrows - 2;
24616 else if (EQ (Vdisplay_line_numbers, Qvisual))
24617 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24618 else
24619 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24620 max_lnum = max (1, max_lnum);
24621 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24622 eassert (it->lnum_width > 0);
24623 }
24624 if (EQ (Vdisplay_line_numbers, Qrelative))
24625 lnum_offset = it->pt_lnum;
24626 else if (EQ (Vdisplay_line_numbers, Qvisual))
24627 lnum_offset = 0;
24628 else if (display_line_numbers_offset)
24629 lnum_offset -= display_line_numbers_offset;
24630
24631
24632
24633 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24634 if ((EQ (Vdisplay_line_numbers, Qrelative)
24635 || EQ (Vdisplay_line_numbers, Qvisual))
24636 && lnum_to_display == 0
24637 && !NILP (Vdisplay_line_numbers_current_absolute))
24638 lnum_to_display = it->pt_lnum + 1;
24639
24640
24641
24642
24643
24644 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24645 strcat (lnum_buf, " ");
24646
24647
24648 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24649
24650 DEFAULT_FACE_ID);
24651 scratch_glyph_row.reversed_p = false;
24652 scratch_glyph_row.used[TEXT_AREA] = 0;
24653 SET_TEXT_POS (tem_it.position, 0, 0);
24654 tem_it.avoid_cursor_p = true;
24655 tem_it.bidi_p = true;
24656 tem_it.bidi_it.type = WEAK_EN;
24657
24658
24659
24660 tem_it.bidi_it.resolved_level = 2;
24661
24662
24663
24664 int width_limit =
24665 tem_it.last_visible_x - tem_it.first_visible_x
24666 - 3 * FRAME_COLUMN_WIDTH (it->f);
24667
24668 tem_it.face_id = lnum_face_id;
24669
24670
24671 if (lnum_face_id != current_lnum_face_id
24672 && (EQ (Vdisplay_line_numbers, Qvisual)
24673 ? this_line == 0
24674 : this_line == it->pt_lnum)
24675 && it->what != IT_EOB)
24676 tem_it.face_id = current_lnum_face_id;
24677 else if (!beyond_zv)
24678 {
24679 if (display_line_numbers_major_tick > 0
24680 && (lnum_to_display % display_line_numbers_major_tick == 0))
24681 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24682 0, DEFAULT_FACE_ID);
24683 else if (display_line_numbers_minor_tick > 0
24684 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24685 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24686 0, DEFAULT_FACE_ID);
24687 }
24688
24689
24690 for (const char *p = lnum_buf; *p; p++)
24691 {
24692
24693
24694 if (beyond_zv
24695
24696 || (!EQ (Vdisplay_line_numbers, Qvisual)
24697 && (it->continuation_lines_width > 0
24698 || (this_line == last_line && !first_time))))
24699 tem_it.c = tem_it.char_to_display = ' ';
24700 else
24701 tem_it.c = tem_it.char_to_display = *p;
24702 tem_it.len = 1;
24703
24704 SET_TEXT_POS (tem_it.position, -1, -1);
24705 PRODUCE_GLYPHS (&tem_it);
24706
24707
24708
24709 if (tem_it.current_x >= width_limit)
24710 {
24711 it->lnum_width = 0;
24712 it->lnum_pixel_width = 0;
24713 bidi_unshelve_cache (itdata, false);
24714 inhibit_free_realized_faces = save_free_realized_faces;
24715 return;
24716 }
24717 }
24718
24719 inhibit_free_realized_faces = save_free_realized_faces;
24720
24721
24722 it->lnum_pixel_width = tem_it.current_x;
24723
24724 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24725 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24726 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24727 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24728
24729 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24730
24731 for ( ; g < e; g++)
24732 {
24733 it->current_x += g->pixel_width;
24734
24735
24736
24737 if (it->current_x > it->first_visible_x)
24738 it->hpos++;
24739 if (p)
24740 {
24741 *p++ = *g;
24742 (*u)++;
24743 }
24744 }
24745
24746
24747
24748
24749 if (!beyond_zv)
24750 {
24751 if (it->glyph_row)
24752 {
24753 struct glyph_row *row = it->glyph_row;
24754
24755 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24756 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24757 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24758 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24759 tem_it.max_phys_descent);
24760 }
24761 else
24762 {
24763 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24764 it->max_descent = max (it->max_descent, tem_it.max_descent);
24765 it->max_phys_ascent = max (it->max_phys_ascent,
24766 tem_it.max_phys_ascent);
24767 it->max_phys_descent = max (it->max_phys_descent,
24768 tem_it.max_phys_descent);
24769 }
24770 }
24771
24772 it->line_number_produced_p = true;
24773
24774 bidi_unshelve_cache (itdata, false);
24775 }
24776
24777
24778
24779 static bool
24780 should_produce_line_number (struct it *it)
24781 {
24782 if (NILP (Vdisplay_line_numbers))
24783 return false;
24784
24785
24786 if (MINI_WINDOW_P (it->w))
24787 return false;
24788
24789 #ifdef HAVE_WINDOW_SYSTEM
24790
24791 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24792 return false;
24793 #endif
24794
24795
24796
24797
24798
24799 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24800 Qdisplay_line_numbers_disable,
24801 it->window);
24802
24803
24804
24805 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24806 val = disable_line_numbers_overlay_at_eob ();
24807 return NILP (val) ? true : false;
24808 }
24809
24810
24811
24812
24813
24814 static bool
24815 row_text_area_empty (struct glyph_row *row)
24816 {
24817 if (!row->reversed_p)
24818 {
24819 for (struct glyph *g = row->glyphs[TEXT_AREA];
24820 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24821 g++)
24822 if (!NILP (g->object) || g->charpos > 0)
24823 return false;
24824 }
24825 else
24826 {
24827 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24828 g > row->glyphs[TEXT_AREA];
24829 g--)
24830 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24831 return false;
24832 }
24833
24834 return true;
24835 }
24836
24837
24838
24839
24840
24841
24842
24843
24844 static bool
24845 display_line (struct it *it, int cursor_vpos)
24846 {
24847 struct glyph_row *row = it->glyph_row;
24848 Lisp_Object overlay_arrow_string;
24849 struct it wrap_it;
24850 void *wrap_data = NULL;
24851 bool may_wrap = false;
24852 int wrap_x UNINIT;
24853 int wrap_row_used = -1;
24854 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24855 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24856 int wrap_row_extra_line_spacing UNINIT;
24857 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24858 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24859 int cvpos;
24860 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24861 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24862 bool pending_handle_line_prefix = false;
24863 int tab_line = window_wants_tab_line (it->w);
24864 int header_line = window_wants_header_line (it->w);
24865 bool hscroll_this_line = (cursor_vpos >= 0
24866 && it->vpos == cursor_vpos - tab_line - header_line
24867 && hscrolling_current_line_p (it->w));
24868 int first_visible_x = it->first_visible_x;
24869 int last_visible_x = it->last_visible_x;
24870 int x_incr = 0;
24871
24872
24873 eassert (it->hpos == 0 && it->current_x == 0);
24874
24875 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24876 >= it->w->desired_matrix->nrows)
24877 {
24878 it->w->nrows_scale_factor++;
24879 it->f->fonts_changed = true;
24880 return false;
24881 }
24882
24883
24884 prepare_desired_row (it->w, row, false);
24885
24886 row->y = it->current_y;
24887 row->start = it->start;
24888 row->continuation_lines_width = it->continuation_lines_width;
24889 row->displays_text_p = true;
24890 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24891 it->starts_in_middle_of_char_p = false;
24892 it->stretch_adjust = 0;
24893 it->line_number_produced_p = false;
24894
24895
24896
24897
24898 if (hscroll_this_line)
24899 x_incr =
24900 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24901 * FRAME_COLUMN_WIDTH (it->f);
24902
24903 bool line_number_needed = should_produce_line_number (it);
24904
24905
24906
24907
24908 if (it->current_x < it->first_visible_x + x_incr)
24909 {
24910 enum move_it_result move_result;
24911
24912 this_line_min_pos = row->start.pos;
24913 if (hscroll_this_line)
24914 {
24915 it->first_visible_x += x_incr;
24916 it->last_visible_x += x_incr;
24917 }
24918 if (current_buffer->long_line_optimizations_p
24919 && it->line_wrap == TRUNCATE
24920 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24921 {
24922
24923
24924
24925
24926 ptrdiff_t chars_to_skip =
24927 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24928 move_result = fast_move_it_horizontally (it, chars_to_skip);
24929
24930 if (move_result == MOVE_X_REACHED)
24931 it->current_x = it->first_visible_x;
24932 else
24933 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24934 }
24935 else
24936 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24937 MOVE_TO_POS | MOVE_TO_X);
24938
24939
24940
24941
24942
24943
24944 if (it->current_x < it->first_visible_x
24945 && (move_result == MOVE_NEWLINE_OR_CR
24946 || move_result == MOVE_POS_MATCH_OR_ZV))
24947 it->current_x = it->first_visible_x;
24948
24949
24950
24951 it->line_number_produced_p = false;
24952
24953
24954
24955
24956
24957
24958
24959
24960 min_pos = CHARPOS (this_line_min_pos);
24961 min_bpos = BYTEPOS (this_line_min_pos);
24962
24963
24964 if (line_number_needed)
24965 maybe_produce_line_number (it);
24966 }
24967 else if (it->area == TEXT_AREA)
24968 {
24969
24970 if (line_number_needed)
24971 maybe_produce_line_number (it);
24972
24973
24974
24975 handle_line_prefix (it);
24976 }
24977 else
24978 {
24979
24980
24981
24982
24983
24984
24985
24986 pending_handle_line_prefix = true;
24987 }
24988
24989
24990
24991 row->ascent = it->max_ascent;
24992 row->height = it->max_ascent + it->max_descent;
24993 row->phys_ascent = it->max_phys_ascent;
24994 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24995 row->extra_line_spacing = it->max_extra_line_spacing;
24996
24997
24998 #define RECORD_MAX_MIN_POS(IT) \
24999 do \
25000 { \
25001 bool composition_p \
25002 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
25003 ptrdiff_t current_pos = \
25004 composition_p ? (IT)->cmp_it.charpos \
25005 : IT_CHARPOS (*(IT)); \
25006 ptrdiff_t current_bpos = \
25007 composition_p ? CHAR_TO_BYTE (current_pos) \
25008 : IT_BYTEPOS (*(IT)); \
25009 if (current_pos < min_pos) \
25010 { \
25011 min_pos = current_pos; \
25012 min_bpos = current_bpos; \
25013 } \
25014 if (IT_CHARPOS (*it) > max_pos) \
25015 { \
25016 max_pos = IT_CHARPOS (*it); \
25017 max_bpos = IT_BYTEPOS (*it); \
25018 } \
25019 } \
25020 while (false)
25021
25022
25023
25024 while (true)
25025 {
25026 int n_glyphs_before, hpos_before, x_before;
25027 int x, nglyphs;
25028 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
25029
25030
25031
25032 if (!get_next_display_element (it))
25033 {
25034 bool row_has_glyphs = false;
25035
25036
25037
25038
25039 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25040 row->exact_window_width_line_p = true;
25041 else if ((append_space_for_newline (it, true)
25042 && row->used[TEXT_AREA] == 1)
25043 || row->used[TEXT_AREA] == 0
25044 || (row_has_glyphs = row_text_area_empty (row)))
25045 {
25046 row->glyphs[TEXT_AREA]->charpos = -1;
25047
25048
25049 if (!row_has_glyphs)
25050 row->displays_text_p = false;
25051
25052 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
25053 && (!MINI_WINDOW_P (it->w)))
25054 row->indicate_empty_line_p = true;
25055 }
25056
25057 it->continuation_lines_width = 0;
25058
25059
25060
25061
25062 it->font_height = Qnil;
25063 it->voffset = 0;
25064 row->ends_at_zv_p = true;
25065
25066
25067
25068
25069
25070
25071
25072
25073 if (row->reversed_p
25074 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
25075 != DEFAULT_FACE_ID)
25076 extend_face_to_end_of_line (it);
25077 break;
25078 }
25079
25080
25081
25082 n_glyphs_before = row->used[TEXT_AREA];
25083 x = it->current_x;
25084
25085
25086
25087 if (it->line_wrap != TRUNCATE)
25088 {
25089 ascent = it->max_ascent;
25090 descent = it->max_descent;
25091 phys_ascent = it->max_phys_ascent;
25092 phys_descent = it->max_phys_descent;
25093
25094 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
25095 {
25096 bool next_may_wrap = may_wrap;
25097
25098 if (char_can_wrap_after (it))
25099 next_may_wrap = true;
25100 else
25101 next_may_wrap = false;
25102
25103 if (may_wrap && char_can_wrap_before (it))
25104 {
25105 SAVE_IT (wrap_it, *it, wrap_data);
25106 wrap_x = x;
25107 wrap_row_used = row->used[TEXT_AREA];
25108 wrap_row_ascent = row->ascent;
25109 wrap_row_height = row->height;
25110 wrap_row_phys_ascent = row->phys_ascent;
25111 wrap_row_phys_height = row->phys_height;
25112 wrap_row_extra_line_spacing = row->extra_line_spacing;
25113 wrap_row_min_pos = min_pos;
25114 wrap_row_min_bpos = min_bpos;
25115 wrap_row_max_pos = max_pos;
25116 wrap_row_max_bpos = max_bpos;
25117 }
25118
25119 may_wrap = next_may_wrap;
25120 }
25121 }
25122
25123 PRODUCE_GLYPHS (it);
25124
25125
25126
25127 if (it->area != TEXT_AREA)
25128 {
25129 row->ascent = max (row->ascent, it->max_ascent);
25130 row->height = max (row->height, it->max_ascent + it->max_descent);
25131 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25132 row->phys_height = max (row->phys_height,
25133 it->max_phys_ascent + it->max_phys_descent);
25134 row->extra_line_spacing = max (row->extra_line_spacing,
25135 it->max_extra_line_spacing);
25136 set_iterator_to_next (it, true);
25137
25138
25139
25140 if (it->area == TEXT_AREA && pending_handle_line_prefix)
25141 {
25142
25143 if (line_number_needed)
25144 maybe_produce_line_number (it);
25145
25146 pending_handle_line_prefix = false;
25147 handle_line_prefix (it);
25148 }
25149 continue;
25150 }
25151
25152
25153
25154
25155
25156
25157
25158
25159
25160
25161 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
25162 hpos_before = it->hpos;
25163 x_before = x;
25164
25165 if (
25166 nglyphs > 0
25167
25168 && it->current_x < it->last_visible_x)
25169 {
25170 it->hpos += nglyphs;
25171 row->ascent = max (row->ascent, it->max_ascent);
25172 row->height = max (row->height, it->max_ascent + it->max_descent);
25173 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25174 row->phys_height = max (row->phys_height,
25175 it->max_phys_ascent + it->max_phys_descent);
25176 row->extra_line_spacing = max (row->extra_line_spacing,
25177 it->max_extra_line_spacing);
25178 if (it->current_x - it->pixel_width < it->first_visible_x
25179
25180
25181
25182 && !line_number_needed
25183
25184
25185
25186
25187 && !row->reversed_p)
25188 row->x = x - it->first_visible_x;
25189
25190
25191 if (it->bidi_p)
25192 RECORD_MAX_MIN_POS (it);
25193 }
25194 else
25195 {
25196 int i, new_x;
25197 struct glyph *glyph;
25198
25199 for (i = 0; i < nglyphs; ++i, x = new_x)
25200 {
25201
25202
25203
25204 if (!row->reversed_p)
25205 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25206 else
25207 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25208 new_x = x + glyph->pixel_width;
25209
25210 if (
25211 it->line_wrap != TRUNCATE
25212 && (
25213 new_x > it->last_visible_x
25214
25215 || (new_x == it->last_visible_x
25216 && FRAME_WINDOW_P (it->f)
25217 && (row->reversed_p
25218 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25219 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25220 {
25221
25222
25223 if (it->hpos == 0
25224 || (new_x == it->last_visible_x
25225 && FRAME_WINDOW_P (it->f)
25226 && (row->reversed_p
25227 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25228 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25229 {
25230
25231
25232
25233
25234 row->continued_p = true;
25235 it->current_x = new_x;
25236 it->continuation_lines_width += new_x;
25237 ++it->hpos;
25238 if (i == nglyphs - 1)
25239 {
25240
25241
25242 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25243 && wrap_row_used > 0
25244
25245
25246
25247
25248
25249
25250
25251
25252
25253
25254 && (!may_wrap || !char_can_wrap_before (it)))
25255 goto back_to_wrap;
25256
25257
25258
25259
25260 if (it->bidi_p)
25261 RECORD_MAX_MIN_POS (it);
25262 set_iterator_to_next (it, true);
25263 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25264 {
25265 if (!get_next_display_element (it))
25266 {
25267 row->exact_window_width_line_p = true;
25268 it->continuation_lines_width = 0;
25269 it->font_height = Qnil;
25270 it->voffset = 0;
25271 row->continued_p = false;
25272 row->ends_at_zv_p = true;
25273 }
25274 else if (ITERATOR_AT_END_OF_LINE_P (it))
25275 {
25276 row->continued_p = false;
25277 row->exact_window_width_line_p = true;
25278 }
25279
25280
25281 else if (wrap_row_used > 0
25282
25283
25284
25285
25286
25287
25288
25289
25290
25291 && (!may_wrap || !char_can_wrap_before (it)))
25292 goto back_to_wrap;
25293
25294 }
25295 }
25296 else if (it->bidi_p)
25297 RECORD_MAX_MIN_POS (it);
25298 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25299 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25300 extend_face_to_end_of_line (it);
25301 }
25302 else if (CHAR_GLYPH_PADDING_P (*glyph)
25303 && !FRAME_WINDOW_P (it->f))
25304 {
25305
25306
25307
25308 if (row->reversed_p)
25309 unproduce_glyphs (it, row->used[TEXT_AREA]
25310 - n_glyphs_before);
25311 row->used[TEXT_AREA] = n_glyphs_before;
25312
25313
25314
25315 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25316 < row->glyphs[1 + TEXT_AREA])
25317 produce_special_glyphs (it, IT_CONTINUATION);
25318
25319 row->continued_p = true;
25320 it->current_x = x_before;
25321 it->continuation_lines_width += x_before;
25322
25323
25324
25325 it->max_ascent = ascent;
25326 it->max_descent = descent;
25327 it->max_phys_ascent = phys_ascent;
25328 it->max_phys_descent = phys_descent;
25329 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25330 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25331 extend_face_to_end_of_line (it);
25332 }
25333 else if (wrap_row_used > 0)
25334 {
25335 back_to_wrap:
25336 if (row->reversed_p)
25337 unproduce_glyphs (it,
25338 row->used[TEXT_AREA] - wrap_row_used);
25339 RESTORE_IT (it, &wrap_it, wrap_data);
25340 it->continuation_lines_width += wrap_x;
25341 row->used[TEXT_AREA] = wrap_row_used;
25342 row->ascent = wrap_row_ascent;
25343 row->height = wrap_row_height;
25344 row->phys_ascent = wrap_row_phys_ascent;
25345 row->phys_height = wrap_row_phys_height;
25346 row->extra_line_spacing = wrap_row_extra_line_spacing;
25347 min_pos = wrap_row_min_pos;
25348 min_bpos = wrap_row_min_bpos;
25349 max_pos = wrap_row_max_pos;
25350 max_bpos = wrap_row_max_bpos;
25351 row->continued_p = true;
25352 row->ends_at_zv_p = false;
25353 row->exact_window_width_line_p = false;
25354
25355
25356
25357 extend_face_to_end_of_line (it);
25358 }
25359 else if ((it->what == IT_CHARACTER
25360 || it->what == IT_STRETCH
25361 || it->what == IT_COMPOSITION)
25362 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25363 {
25364
25365
25366
25367
25368
25369 if ((row->reversed_p
25370 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25371 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25372 produce_special_glyphs (it, IT_CONTINUATION);
25373 it->continuation_lines_width += it->last_visible_x;
25374 row->ends_in_middle_of_char_p = true;
25375 row->continued_p = true;
25376 glyph->pixel_width = it->last_visible_x - x;
25377 it->starts_in_middle_of_char_p = true;
25378 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25379 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25380 extend_face_to_end_of_line (it);
25381 }
25382 else
25383 {
25384
25385
25386
25387 if (row->reversed_p)
25388 unproduce_glyphs (it, row->used[TEXT_AREA]
25389 - (n_glyphs_before + i));
25390 row->used[TEXT_AREA] = n_glyphs_before + i;
25391
25392
25393 it->current_x = x_before;
25394 it->continuation_lines_width += x;
25395 if (!FRAME_WINDOW_P (it->f)
25396 || (row->reversed_p
25397 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25398 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25399 produce_special_glyphs (it, IT_CONTINUATION);
25400 row->continued_p = true;
25401
25402 extend_face_to_end_of_line (it);
25403
25404 if (nglyphs > 1 && i > 0)
25405 {
25406 row->ends_in_middle_of_char_p = true;
25407 it->starts_in_middle_of_char_p = true;
25408 }
25409
25410
25411
25412 it->max_ascent = ascent;
25413 it->max_descent = descent;
25414 it->max_phys_ascent = phys_ascent;
25415 it->max_phys_descent = phys_descent;
25416 }
25417
25418 break;
25419 }
25420 else if (new_x > it->first_visible_x)
25421 {
25422
25423 ++it->hpos;
25424
25425
25426
25427
25428 if (it->bidi_p)
25429 RECORD_MAX_MIN_POS (it);
25430
25431 if (x < it->first_visible_x && !row->reversed_p
25432 && !line_number_needed)
25433
25434
25435
25436
25437
25438
25439 row->x = x - it->first_visible_x;
25440
25441
25442
25443
25444
25445
25446 if (row->reversed_p
25447 && new_x > it->last_visible_x
25448 && !line_number_needed
25449 && !(it->line_wrap == TRUNCATE
25450 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25451 {
25452 eassert (FRAME_WINDOW_P (it->f));
25453 row->x = it->last_visible_x - new_x;
25454 }
25455 }
25456 else
25457 {
25458
25459
25460
25461
25462
25463 eassert (it->first_visible_x <= it->last_visible_x);
25464 }
25465 }
25466
25467
25468 if (it->bidi_p && nglyphs == 0)
25469 RECORD_MAX_MIN_POS (it);
25470
25471 row->ascent = max (row->ascent, it->max_ascent);
25472 row->height = max (row->height, it->max_ascent + it->max_descent);
25473 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25474 row->phys_height = max (row->phys_height,
25475 it->max_phys_ascent + it->max_phys_descent);
25476 row->extra_line_spacing = max (row->extra_line_spacing,
25477 it->max_extra_line_spacing);
25478
25479
25480 if (row->continued_p || row->ends_at_zv_p)
25481 break;
25482 }
25483
25484 at_end_of_line:
25485
25486
25487
25488 if (ITERATOR_AT_END_OF_LINE_P (it))
25489 {
25490 int used_before = row->used[TEXT_AREA];
25491
25492 row->ends_in_newline_from_string_p = STRINGP (it->object);
25493
25494
25495
25496 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25497 append_space_for_newline (it, false);
25498
25499
25500 extend_face_to_end_of_line (it);
25501
25502
25503 if (used_before == 0)
25504 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25505
25506
25507
25508 it->eol_pos = it->current.pos;
25509
25510
25511 set_iterator_to_next (it, true);
25512 it->continuation_lines_width = 0;
25513 break;
25514 }
25515
25516
25517
25518
25519
25520
25521
25522
25523 bool overwide_wrap_prefix =
25524 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25525 && it->sp > 0 && it->method == GET_FROM_STRETCH
25526 && it->current_x >= it->last_visible_x
25527 && it->continuation_lines_width > 0
25528 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25529
25530
25531
25532 if (!overwide_wrap_prefix)
25533 set_iterator_to_next (it, true);
25534
25535
25536
25537 if (it->line_wrap == TRUNCATE
25538 && ((FRAME_WINDOW_P (it->f)
25539
25540
25541
25542
25543 && ((row->reversed_p
25544 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25545 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25546 || it->what == IT_IMAGE))
25547 ? (it->current_x >= it->last_visible_x)
25548 : (it->current_x > it->last_visible_x)))
25549 {
25550
25551 if (!FRAME_WINDOW_P (it->f)
25552 || (row->reversed_p
25553 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25554 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25555 {
25556 int i, n;
25557
25558 if (!row->reversed_p)
25559 {
25560 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25561 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25562 break;
25563 }
25564 else
25565 {
25566 for (i = 0; i < row->used[TEXT_AREA]; i++)
25567 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25568 break;
25569
25570
25571
25572
25573
25574 unproduce_glyphs (it, i + 1);
25575
25576 i = row->used[TEXT_AREA] - (i + 1);
25577 }
25578
25579
25580
25581
25582 if (it->current_x > it->last_visible_x)
25583 {
25584 it->current_x = x_before;
25585 if (!FRAME_WINDOW_P (it->f))
25586 {
25587 for (n = row->used[TEXT_AREA]; i < n; ++i)
25588 {
25589 row->used[TEXT_AREA] = i;
25590 produce_special_glyphs (it, IT_TRUNCATION);
25591 }
25592 }
25593 else
25594 {
25595 row->used[TEXT_AREA] = i;
25596 produce_special_glyphs (it, IT_TRUNCATION);
25597 }
25598 it->hpos = hpos_before;
25599 }
25600 }
25601 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25602 {
25603
25604 if (!get_next_display_element (it))
25605 {
25606 it->continuation_lines_width = 0;
25607 it->font_height = Qnil;
25608 it->voffset = 0;
25609 row->ends_at_zv_p = true;
25610 row->exact_window_width_line_p = true;
25611 break;
25612 }
25613 if (ITERATOR_AT_END_OF_LINE_P (it))
25614 {
25615 row->exact_window_width_line_p = true;
25616 goto at_end_of_line;
25617 }
25618 it->current_x = x_before;
25619 it->hpos = hpos_before;
25620 }
25621
25622 row->truncated_on_right_p = true;
25623 it->continuation_lines_width = 0;
25624 reseat_at_next_visible_line_start (it, false);
25625
25626
25627
25628
25629 if (IT_BYTEPOS (*it) > BEG_BYTE)
25630 row->ends_at_zv_p =
25631 IT_BYTEPOS (*it) >= ZV_BYTE
25632 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25633 else
25634 row->ends_at_zv_p = false;
25635 break;
25636 }
25637 }
25638
25639 if (wrap_data)
25640 bidi_unshelve_cache (wrap_data, true);
25641
25642
25643
25644 if (it->first_visible_x
25645 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25646 {
25647 if (!FRAME_WINDOW_P (it->f)
25648 || (((row->reversed_p
25649 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25650 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25651
25652
25653 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25654 insert_left_trunc_glyphs (it);
25655 row->truncated_on_left_p = true;
25656 }
25657
25658
25659
25660
25661
25662
25663 row->end = it->current;
25664 if (!it->bidi_p)
25665 {
25666 row->minpos = row->start.pos;
25667 row->maxpos = row->end.pos;
25668 }
25669 else
25670 {
25671
25672
25673
25674
25675 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25676 }
25677
25678
25679
25680
25681
25682 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25683 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25684 !NILP (overlay_arrow_string)))
25685 {
25686
25687 if (STRINGP (overlay_arrow_string))
25688 {
25689 struct glyph_row *arrow_row
25690 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25691 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25692 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25693 struct glyph *p = row->glyphs[TEXT_AREA];
25694 struct glyph *p2, *end;
25695
25696
25697 while (glyph < arrow_end)
25698 *p++ = *glyph++;
25699
25700
25701 p2 = p;
25702 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25703 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25704 ++p2;
25705 if (p2 > p)
25706 {
25707 while (p2 < end)
25708 *p++ = *p2++;
25709 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25710 }
25711 }
25712 else
25713 {
25714 eassert (FIXNUMP (overlay_arrow_string));
25715 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25716 }
25717 overlay_arrow_seen = true;
25718 }
25719
25720
25721 if (!NILP (Vshow_trailing_whitespace))
25722 highlight_trailing_whitespace (it);
25723
25724
25725 compute_line_metrics (it);
25726
25727
25728
25729
25730
25731
25732
25733 row->ends_in_ellipsis_p
25734 = (it->method == GET_FROM_DISPLAY_VECTOR
25735 && it->ellipsis_p);
25736
25737
25738 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25739 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25740 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25741 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25742
25743 it->left_user_fringe_bitmap = 0;
25744 it->left_user_fringe_face_id = 0;
25745 it->right_user_fringe_bitmap = 0;
25746 it->right_user_fringe_face_id = 0;
25747
25748
25749
25750
25751
25752
25753 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25754 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25755 row->redraw_fringe_bitmaps_p = true;
25756
25757
25758 cvpos = it->w->cursor.vpos;
25759 if ((cvpos < 0
25760
25761
25762
25763
25764
25765
25766
25767
25768 || (it->bidi_p
25769 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25770 && PT >= MATRIX_ROW_START_CHARPOS (row)
25771 && PT <= MATRIX_ROW_END_CHARPOS (row)
25772 && cursor_row_p (row))
25773 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25774
25775
25776
25777
25778
25779 it->current_x = it->hpos = 0;
25780 it->current_y += row->height;
25781
25782
25783 if (hscroll_this_line)
25784 {
25785 it->first_visible_x = first_visible_x;
25786 it->last_visible_x = last_visible_x;
25787 }
25788 SET_TEXT_POS (it->eol_pos, 0, 0);
25789 ++it->vpos;
25790 ++it->glyph_row;
25791
25792
25793
25794
25795 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25796 it->glyph_row->reversed_p = row->reversed_p;
25797 it->start = row->end;
25798 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25799
25800 #undef RECORD_MAX_MIN_POS
25801 }
25802
25803 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25804 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25805 doc:
25806
25807
25808
25809
25810
25811
25812
25813
25814 )
25815 (Lisp_Object buffer)
25816 {
25817 struct buffer *buf = current_buffer;
25818 struct buffer *old = buf;
25819
25820 if (! NILP (buffer))
25821 {
25822 CHECK_BUFFER (buffer);
25823 buf = XBUFFER (buffer);
25824 }
25825
25826 if (NILP (BVAR (buf, bidi_display_reordering))
25827 || NILP (BVAR (buf, enable_multibyte_characters))
25828
25829
25830 || redisplay__inhibit_bidi)
25831 return Qleft_to_right;
25832 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25833 return BVAR (buf, bidi_paragraph_direction);
25834 else
25835 {
25836
25837
25838
25839 struct bidi_it itb;
25840 ptrdiff_t pos = BUF_PT (buf);
25841 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25842 int c;
25843 void *itb_data = bidi_shelve_cache ();
25844
25845 set_buffer_temp (buf);
25846
25847
25848
25849
25850
25851 if (pos >= ZV && pos > BEGV)
25852 dec_both (&pos, &bytepos);
25853 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25854 if (fast_looking_at (trailing_white_space,
25855 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25856 {
25857 while ((c = FETCH_BYTE (bytepos)) == '\n'
25858 || c == ' ' || c == '\t' || c == '\f')
25859 {
25860 if (bytepos <= BEGV_BYTE)
25861 break;
25862 bytepos--;
25863 pos--;
25864 }
25865 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25866 bytepos--;
25867 }
25868 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25869 itb.paragraph_dir = NEUTRAL_DIR;
25870 itb.string.s = NULL;
25871 itb.string.lstring = Qnil;
25872 itb.string.bufpos = 0;
25873 itb.string.from_disp_str = false;
25874 itb.string.unibyte = false;
25875
25876
25877
25878 itb.w = NULL;
25879 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25880 bidi_unshelve_cache (itb_data, false);
25881 set_buffer_temp (old);
25882 switch (itb.paragraph_dir)
25883 {
25884 case L2R:
25885 return Qleft_to_right;
25886 break;
25887 case R2L:
25888 return Qright_to_left;
25889 break;
25890 default:
25891 emacs_abort ();
25892 }
25893 }
25894 }
25895
25896 DEFUN ("bidi-find-overridden-directionality",
25897 Fbidi_find_overridden_directionality,
25898 Sbidi_find_overridden_directionality, 3, 4, 0,
25899 doc:
25900
25901
25902
25903
25904
25905
25906
25907
25908
25909
25910
25911
25912
25913
25914
25915
25916
25917
25918
25919
25920
25921
25922
25923
25924
25925
25926
25927
25928
25929
25930
25931
25932
25933
25934
25935
25936 )
25937 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25938 {
25939 struct buffer *buf = current_buffer;
25940 struct buffer *old = buf;
25941 struct window *w = NULL;
25942 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25943 struct bidi_it itb;
25944 ptrdiff_t from_pos, to_pos, from_bpos;
25945 void *itb_data;
25946
25947 if (!NILP (object))
25948 {
25949 if (BUFFERP (object))
25950 buf = XBUFFER (object);
25951 else if (WINDOWP (object))
25952 {
25953 w = decode_live_window (object);
25954 buf = XBUFFER (w->contents);
25955 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25956 }
25957 else
25958 CHECK_STRING (object);
25959 }
25960
25961 if (STRINGP (object))
25962 {
25963
25964
25965 if (!STRING_MULTIBYTE (object)
25966
25967
25968
25969 || redisplay__inhibit_bidi)
25970 return Qnil;
25971
25972 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25973 if (from_pos >= SCHARS (object))
25974 return Qnil;
25975
25976
25977 itb_data = bidi_shelve_cache ();
25978 itb.paragraph_dir = NEUTRAL_DIR;
25979 itb.string.lstring = object;
25980 itb.string.s = NULL;
25981 itb.string.schars = SCHARS (object);
25982 itb.string.bufpos = 0;
25983 itb.string.from_disp_str = false;
25984 itb.string.unibyte = false;
25985 itb.w = w;
25986 bidi_init_it (0, 0, frame_window_p, &itb);
25987 }
25988 else
25989 {
25990
25991
25992 if (NILP (BVAR (buf, bidi_display_reordering))
25993 || NILP (BVAR (buf, enable_multibyte_characters))
25994
25995
25996
25997 || redisplay__inhibit_bidi)
25998 return Qnil;
25999
26000 set_buffer_temp (buf);
26001 validate_region (&from, &to);
26002 from_pos = XFIXNUM (from);
26003 to_pos = XFIXNUM (to);
26004 if (from_pos >= ZV)
26005 return Qnil;
26006
26007
26008 itb_data = bidi_shelve_cache ();
26009 from_bpos = CHAR_TO_BYTE (from_pos);
26010 if (from_pos == BEGV)
26011 {
26012 itb.charpos = BEGV;
26013 itb.bytepos = BEGV_BYTE;
26014 }
26015 else if (FETCH_BYTE (from_bpos - 1) == '\n')
26016 {
26017 itb.charpos = from_pos;
26018 itb.bytepos = from_bpos;
26019 }
26020 else
26021 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
26022 -1, &itb.bytepos);
26023 itb.paragraph_dir = NEUTRAL_DIR;
26024 itb.string.s = NULL;
26025 itb.string.lstring = Qnil;
26026 itb.string.bufpos = 0;
26027 itb.string.from_disp_str = false;
26028 itb.string.unibyte = false;
26029 itb.w = w;
26030 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
26031 }
26032
26033 ptrdiff_t found;
26034 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
26035 do {
26036 bidi_paragraph_init (bdir, &itb, false);
26037 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
26038 ;
26039 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
26040
26041 bidi_unshelve_cache (itb_data, false);
26042 set_buffer_temp (old);
26043
26044 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
26045 }
26046
26047 DEFUN ("move-point-visually", Fmove_point_visually,
26048 Smove_point_visually, 1, 1, 0,
26049 doc:
26050
26051
26052
26053 )
26054 (Lisp_Object direction)
26055 {
26056 struct window *w = XWINDOW (selected_window);
26057 struct buffer *b = XBUFFER (w->contents);
26058 struct glyph_row *row;
26059 int dir;
26060 Lisp_Object paragraph_dir;
26061
26062 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
26063 (!(ROW)->continued_p \
26064 && NILP ((GLYPH)->object) \
26065 && (GLYPH)->type == CHAR_GLYPH \
26066 && (GLYPH)->u.ch == ' ' \
26067 && (GLYPH)->charpos >= 0 \
26068 && !(GLYPH)->avoid_cursor_p)
26069
26070 CHECK_FIXNUM (direction);
26071 dir = XFIXNUM (direction);
26072 if (dir > 0)
26073 dir = 1;
26074 else
26075 dir = -1;
26076
26077
26078
26079
26080 if (w->window_end_valid
26081 && !windows_or_buffers_changed
26082 && b
26083 && !b->clip_changed
26084 && !b->prevent_redisplay_optimizations_p
26085 && !window_outdated (w)
26086
26087
26088
26089 && w->last_point == BUF_PT (b)
26090 && w->cursor.vpos >= 0
26091 && w->cursor.vpos < w->current_matrix->nrows
26092 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
26093 {
26094 struct glyph *g = row->glyphs[TEXT_AREA];
26095 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
26096 struct glyph *gpt = g + w->cursor.hpos;
26097
26098 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
26099 {
26100 if (BUFFERP (g->object) && g->charpos != PT)
26101 {
26102 SET_PT (g->charpos);
26103 w->cursor.vpos = -1;
26104 return make_fixnum (PT);
26105 }
26106 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
26107 {
26108 ptrdiff_t new_pos;
26109
26110 if (BUFFERP (gpt->object))
26111 {
26112 new_pos = PT;
26113 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
26114 new_pos += (row->reversed_p ? -dir : dir);
26115 else
26116 new_pos -= (row->reversed_p ? -dir : dir);
26117 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
26118
26119
26120 if (new_pos == PT)
26121 break;
26122 }
26123 else if (BUFFERP (g->object))
26124 new_pos = g->charpos;
26125 else
26126 break;
26127 SET_PT (new_pos);
26128 w->cursor.vpos = -1;
26129 return make_fixnum (PT);
26130 }
26131 else if (ROW_GLYPH_NEWLINE_P (row, g))
26132 {
26133
26134
26135
26136 if (g->charpos > 0)
26137 SET_PT (g->charpos);
26138 else if (row->ends_at_zv_p && PT != ZV)
26139 SET_PT (ZV);
26140 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
26141 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26142 else
26143 break;
26144 w->cursor.vpos = -1;
26145 return make_fixnum (PT);
26146 }
26147 }
26148 if (g == e || NILP (g->object))
26149 {
26150 if (row->truncated_on_left_p || row->truncated_on_right_p)
26151 goto simulate_display;
26152 if (!row->reversed_p)
26153 row += dir;
26154 else
26155 row -= dir;
26156 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
26157 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
26158 goto simulate_display;
26159
26160 if (dir > 0)
26161 {
26162 if (row->reversed_p && !row->continued_p)
26163 {
26164 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26165 w->cursor.vpos = -1;
26166 return make_fixnum (PT);
26167 }
26168 g = row->glyphs[TEXT_AREA];
26169 e = g + row->used[TEXT_AREA];
26170 for ( ; g < e; g++)
26171 {
26172 if (BUFFERP (g->object)
26173
26174
26175
26176 || ROW_GLYPH_NEWLINE_P (row, g)
26177
26178
26179 || (row->ends_at_zv_p
26180 && !row->reversed_p
26181 && NILP (g->object)
26182 && g->type == CHAR_GLYPH
26183 && g->u.ch == ' '))
26184 {
26185 if (g->charpos > 0)
26186 SET_PT (g->charpos);
26187 else if (!row->reversed_p
26188 && row->ends_at_zv_p
26189 && PT != ZV)
26190 SET_PT (ZV);
26191 else
26192 continue;
26193 w->cursor.vpos = -1;
26194 return make_fixnum (PT);
26195 }
26196 }
26197 }
26198 else
26199 {
26200 if (!row->reversed_p && !row->continued_p)
26201 {
26202 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26203 w->cursor.vpos = -1;
26204 return make_fixnum (PT);
26205 }
26206 e = row->glyphs[TEXT_AREA];
26207 g = e + row->used[TEXT_AREA] - 1;
26208 for ( ; g >= e; g--)
26209 {
26210 if (BUFFERP (g->object)
26211 || (ROW_GLYPH_NEWLINE_P (row, g)
26212 && g->charpos > 0)
26213
26214
26215
26216 || g->type == STRETCH_GLYPH
26217 || (row->ends_at_zv_p
26218 && row->reversed_p
26219 && NILP (g->object)
26220 && g->type == CHAR_GLYPH
26221 && g->u.ch == ' '))
26222 {
26223 if (g->charpos > 0)
26224 SET_PT (g->charpos);
26225 else if (row->reversed_p
26226 && row->ends_at_zv_p
26227 && PT != ZV)
26228 SET_PT (ZV);
26229 else
26230 continue;
26231 w->cursor.vpos = -1;
26232 return make_fixnum (PT);
26233 }
26234 }
26235 }
26236 }
26237 }
26238
26239 simulate_display:
26240
26241
26242
26243
26244 if (b)
26245 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26246 else
26247 paragraph_dir = Qleft_to_right;
26248 if (EQ (paragraph_dir, Qright_to_left))
26249 dir = -dir;
26250 if (PT <= BEGV && dir < 0)
26251 xsignal0 (Qbeginning_of_buffer);
26252 else if (PT >= ZV && dir > 0)
26253 xsignal0 (Qend_of_buffer);
26254 else
26255 {
26256 struct text_pos pt;
26257 struct it it;
26258 int pt_x, target_x, pixel_width, pt_vpos;
26259 bool at_eol_p;
26260 bool overshoot_expected = false;
26261 bool target_is_eol_p = false;
26262 void *itdata = bidi_shelve_cache ();
26263
26264
26265 SET_TEXT_POS (pt, PT, PT_BYTE);
26266 start_display (&it, w, pt);
26267
26268
26269
26270
26271
26272
26273 if (it.line_wrap == TRUNCATE)
26274 it.last_visible_x = DISP_INFINITY;
26275
26276 if (it.cmp_it.id < 0
26277 && it.method == GET_FROM_STRING
26278 && it.area == TEXT_AREA
26279 && it.string_from_display_prop_p
26280 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26281 overshoot_expected = true;
26282
26283
26284
26285
26286
26287 reseat:
26288 reseat_at_previous_visible_line_start (&it);
26289 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26290 if (IT_CHARPOS (it) != PT)
26291 {
26292 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26293 -1, -1, -1, MOVE_TO_POS);
26294
26295
26296
26297 if (it.method == GET_FROM_DISPLAY_VECTOR
26298 && it.current.dpvec_index > 0
26299 && !overshoot_expected)
26300 {
26301 overshoot_expected = true;
26302 goto reseat;
26303 }
26304 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26305 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26306 }
26307 pt_x = it.current_x;
26308 pt_vpos = it.vpos;
26309 if (dir > 0 || overshoot_expected)
26310 {
26311 struct glyph_row *row = it.glyph_row;
26312
26313
26314
26315
26316 if (pt_x == 0)
26317 get_next_display_element (&it);
26318 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26319 it.glyph_row = NULL;
26320 PRODUCE_GLYPHS (&it);
26321 it.glyph_row = row;
26322
26323
26324
26325 it.current_x = pt_x;
26326 }
26327 else
26328 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26329 pixel_width = it.pixel_width;
26330 if (overshoot_expected && at_eol_p)
26331 pixel_width = 0;
26332 else if (pixel_width <= 0)
26333 pixel_width = 1;
26334
26335
26336
26337
26338 if (overshoot_expected)
26339 {
26340 if (it.bidi_p)
26341 pt_x += pixel_width * it.bidi_it.scan_dir;
26342 else
26343 pt_x += pixel_width;
26344 }
26345
26346
26347
26348
26349
26350
26351
26352 if (dir > 0)
26353 target_x = pt_x + pixel_width;
26354 else
26355 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26356
26357
26358
26359
26360
26361 if (dir < 0)
26362 {
26363 if (pt_x > 0)
26364 {
26365 start_display (&it, w, pt);
26366 if (it.line_wrap == TRUNCATE)
26367 it.last_visible_x = DISP_INFINITY;
26368 reseat_at_previous_visible_line_start (&it);
26369 it.current_x = it.current_y = it.hpos = 0;
26370 if (pt_vpos != 0)
26371 move_it_by_lines (&it, pt_vpos);
26372 }
26373 else
26374 {
26375 move_it_by_lines (&it, -1);
26376 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26377 target_is_eol_p = true;
26378
26379
26380
26381
26382
26383
26384
26385
26386
26387
26388 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26389 {
26390 void *it_data = NULL;
26391 struct it it2;
26392
26393 SAVE_IT (it2, it, it_data);
26394 move_it_in_display_line_to (&it, ZV, target_x,
26395 MOVE_TO_POS | MOVE_TO_X);
26396
26397
26398 if (it.current_x != target_x)
26399 target_x = it.current_x - 1;
26400 RESTORE_IT (&it, &it2, it_data);
26401 }
26402 }
26403 }
26404 else
26405 {
26406 if (at_eol_p
26407 || (target_x >= it.last_visible_x
26408 && it.line_wrap != TRUNCATE))
26409 {
26410 if (pt_x > 0)
26411 move_it_by_lines (&it, 0);
26412 move_it_by_lines (&it, 1);
26413 target_x = 0;
26414 }
26415 }
26416
26417
26418
26419
26420
26421
26422
26423 if (FRAME_WINDOW_P (it.f) && dir < 0)
26424 {
26425 struct text_pos new_pos;
26426 enum move_it_result rc = MOVE_X_REACHED;
26427
26428 if (it.current_x == 0)
26429 get_next_display_element (&it);
26430 if (it.what == IT_COMPOSITION)
26431 {
26432 new_pos.charpos = it.cmp_it.charpos;
26433 new_pos.bytepos = -1;
26434 }
26435 else
26436 new_pos = it.current.pos;
26437
26438 while (it.current_x + it.pixel_width <= target_x
26439 && (rc == MOVE_X_REACHED
26440
26441
26442
26443 || (it.line_wrap == WORD_WRAP
26444 && rc == MOVE_POS_MATCH_OR_ZV)))
26445 {
26446 int new_x = it.current_x + it.pixel_width;
26447
26448
26449
26450
26451
26452
26453
26454 if (it.what == IT_COMPOSITION)
26455 {
26456 new_pos.charpos = it.cmp_it.charpos;
26457 new_pos.bytepos = -1;
26458 }
26459 else
26460 new_pos = it.current.pos;
26461 if (new_x == it.current_x)
26462 new_x++;
26463 rc = move_it_in_display_line_to (&it, ZV, new_x,
26464 MOVE_TO_POS | MOVE_TO_X);
26465 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26466 break;
26467 }
26468
26469
26470 if (new_pos.bytepos == -1)
26471 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26472 it.current.pos = new_pos;
26473 }
26474 else if (it.current_x != target_x)
26475 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26476
26477
26478
26479 if (dir > 0)
26480 {
26481 while (IT_CHARPOS (it) == PT)
26482 {
26483 set_iterator_to_next (&it, false);
26484 if (!get_next_display_element (&it))
26485 break;
26486 }
26487 }
26488
26489
26490 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26491 bidi_unshelve_cache (itdata, false);
26492 }
26493
26494 return make_fixnum (PT);
26495
26496 #undef ROW_GLYPH_NEWLINE_P
26497 }
26498
26499 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26500 Sbidi_resolved_levels, 0, 1, 0,
26501 doc:
26502
26503
26504
26505
26506
26507
26508
26509
26510
26511
26512
26513
26514
26515
26516
26517
26518
26519
26520
26521
26522
26523
26524
26525
26526
26527 )
26528 (Lisp_Object vpos)
26529 {
26530 struct window *w = XWINDOW (selected_window);
26531 struct buffer *b = XBUFFER (w->contents);
26532 int nrow;
26533 struct glyph_row *row;
26534
26535 if (NILP (vpos))
26536 {
26537 int d1, d2, d3, d4, d5;
26538
26539 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26540 }
26541 else
26542 {
26543 CHECK_FIXNUM (vpos);
26544 nrow = XFIXNUM (vpos);
26545 }
26546
26547
26548 if (w->window_end_valid
26549 && !windows_or_buffers_changed
26550 && b
26551 && !b->clip_changed
26552 && !b->prevent_redisplay_optimizations_p
26553 && !window_outdated (w)
26554 && nrow >= 0
26555 && nrow < w->current_matrix->nrows
26556 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26557 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26558 {
26559 struct glyph *g, *e, *g1;
26560 int nglyphs, i;
26561 Lisp_Object levels;
26562
26563 if (!row->reversed_p)
26564 {
26565 g = g1 = row->glyphs[TEXT_AREA];
26566 e = g + row->used[TEXT_AREA];
26567
26568
26569
26570 while (g < e
26571 && NILP (g->object)
26572 && g->charpos < 0)
26573 g++;
26574 g1 = g;
26575
26576
26577 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26578 nglyphs++;
26579
26580
26581 levels = make_uninit_vector (nglyphs);
26582 for (i = 0; g1 < g; i++, g1++)
26583 ASET (levels, i, make_fixnum (g1->resolved_level));
26584 }
26585 else
26586 {
26587 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26588 e = row->glyphs[TEXT_AREA] - 1;
26589 while (g > e
26590 && NILP (g->object)
26591 && g->charpos < 0)
26592 g--;
26593 g1 = g;
26594 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26595 nglyphs++;
26596 levels = make_uninit_vector (nglyphs);
26597 for (i = 0; g1 > g; i++, g1--)
26598 ASET (levels, i, make_fixnum (g1->resolved_level));
26599 }
26600 return levels;
26601 }
26602 else
26603 return Qnil;
26604 }
26605
26606
26607
26608
26609
26610
26611
26612
26613
26614
26615
26616
26617
26618
26619
26620
26621
26622 static void
26623 display_menu_bar (struct window *w)
26624 {
26625 struct frame *f = XFRAME (WINDOW_FRAME (w));
26626 struct it it;
26627 Lisp_Object items;
26628 int i;
26629
26630
26631 #ifdef HAVE_NTGUI
26632 if (FRAME_W32_P (f))
26633 return;
26634 #endif
26635 #if defined (HAVE_PGTK)
26636 if (FRAME_PGTK_P (f))
26637 return;
26638 #endif
26639
26640 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26641 if (FRAME_X_P (f))
26642 return;
26643 #endif
26644
26645 #ifdef HAVE_NS
26646 if (FRAME_NS_P (f))
26647 return;
26648 #endif
26649
26650 #ifdef HAVE_HAIKU
26651 if (FRAME_HAIKU_P (f))
26652 return;
26653 #endif
26654
26655 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26656 eassert (!FRAME_WINDOW_P (f));
26657 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26658 it.first_visible_x = 0;
26659 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26660 #elif defined (HAVE_X_WINDOWS) || defined (HAVE_ANDROID)
26661 struct window *menu_window = NULL;
26662 struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
26663
26664 if (FRAME_WINDOW_P (f))
26665 {
26666
26667
26668 menu_window = XWINDOW (f->menu_bar_window);
26669 init_iterator (&it, menu_window, -1, -1,
26670 menu_window->desired_matrix->rows,
26671 MENU_FACE_ID);
26672 }
26673 else
26674 #endif
26675 {
26676
26677
26678 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26679 MENU_FACE_ID);
26680 it.first_visible_x = 0;
26681 it.last_visible_x = FRAME_COLS (f);
26682 }
26683
26684
26685
26686
26687 it.paragraph_embedding = L2R;
26688
26689
26690 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26691 {
26692 struct glyph_row *row = it.glyph_row + i;
26693 clear_glyph_row (row);
26694 row->enabled_p = true;
26695 row->full_width_p = true;
26696 row->reversed_p = false;
26697 }
26698
26699
26700 items = FRAME_MENU_BAR_ITEMS (it.f);
26701 for (i = 0; i < ASIZE (items); i += 4)
26702 {
26703 Lisp_Object string;
26704
26705
26706 string = AREF (items, i + 1);
26707 if (NILP (string))
26708 break;
26709
26710
26711 ASET (items, i + 3, make_fixnum (it.hpos));
26712
26713
26714 if (it.current_x < it.last_visible_x)
26715 display_string (NULL, string, Qnil, 0, 0, &it,
26716 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26717 }
26718
26719
26720 if (it.current_x < it.last_visible_x)
26721 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26722
26723
26724 compute_line_metrics (&it);
26725 it.glyph_row->full_width_p = true;
26726 it.glyph_row->continued_p = false;
26727 it.glyph_row->truncated_on_left_p = false;
26728 it.glyph_row->truncated_on_right_p = false;
26729
26730
26731
26732
26733
26734 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
26735
26736 extend_face_to_end_of_line (&it);
26737 if (face->box != FACE_NO_BOX)
26738 {
26739 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26740 + it.glyph_row->used[TEXT_AREA] - 1);
26741 int box_thickness = face->box_vertical_line_width;
26742 last->right_box_line_p = true;
26743
26744
26745
26746
26747
26748
26749 if (box_thickness > 0)
26750 last->pixel_width += max (0, (box_thickness
26751 - (it.current_x - it.last_visible_x)));
26752 }
26753
26754
26755
26756 if (FRAME_WINDOW_P (it.f) && menu_window)
26757 {
26758 struct glyph_row *row;
26759 int delta_height;
26760
26761 row = it.glyph_row;
26762 delta_height
26763 = ((row->y + row->height)
26764 - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
26765
26766 if (delta_height != 0)
26767 {
26768 FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
26769 adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
26770 }
26771 }
26772 #endif
26773 }
26774
26775
26776
26777
26778 #ifndef HAVE_ANDROID
26779
26780
26781 static void
26782 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26783 {
26784 struct glyph *pointers[1 + LAST_AREA];
26785 int to_used = to->used[TEXT_AREA];
26786
26787
26788 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26789
26790
26791 *to = *from;
26792
26793
26794 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26795
26796
26797 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26798 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26799
26800
26801
26802 if (to_used > from->used[TEXT_AREA])
26803 fill_up_frame_row_with_spaces (to, to_used);
26804 }
26805
26806
26807
26808
26809
26810
26811
26812
26813
26814
26815
26816
26817
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827 void
26828 display_tty_menu_item (const char *item_text, int width, int face_id,
26829 int x, int y, bool submenu)
26830 {
26831 struct it it;
26832 struct frame *f = SELECTED_FRAME ();
26833 struct window *w = XWINDOW (f->selected_window);
26834 struct glyph_row *row;
26835 size_t item_len = strlen (item_text);
26836
26837 eassert (FRAME_TERMCAP_P (f));
26838
26839
26840
26841
26842
26843
26844 if (y >= f->desired_matrix->nrows)
26845 return;
26846
26847 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26848 it.first_visible_x = 0;
26849 it.last_visible_x = FRAME_COLS (f) - 1;
26850 row = it.glyph_row;
26851
26852 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26853 bool saved_width = row->full_width_p;
26854 row->full_width_p = true;
26855 bool saved_reversed = row->reversed_p;
26856 row->reversed_p = false;
26857 row->enabled_p = true;
26858
26859
26860
26861 eassert (x < f->desired_matrix->matrix_w);
26862 it.current_x = it.hpos = x;
26863 it.current_y = it.vpos = y;
26864 int saved_used = row->used[TEXT_AREA];
26865 bool saved_truncated = row->truncated_on_right_p;
26866 row->used[TEXT_AREA] = x;
26867 it.face_id = face_id;
26868 it.line_wrap = TRUNCATE;
26869
26870
26871
26872
26873
26874
26875 it.paragraph_embedding = L2R;
26876
26877
26878 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26879 width--;
26880
26881 if (submenu)
26882 {
26883 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26884 item_len, 0, FRAME_COLS (f) - 1, -1);
26885 width -= item_len;
26886
26887 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26888 FRAME_COLS (f) - 1, -1);
26889 }
26890 else
26891 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26892 width, 0, FRAME_COLS (f) - 1, -1);
26893
26894 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26895 row->truncated_on_right_p = saved_truncated;
26896 row->hash = row_hash (row);
26897 row->full_width_p = saved_width;
26898 row->reversed_p = saved_reversed;
26899 }
26900
26901 #endif
26902
26903
26904
26905
26906
26907
26908
26909
26910
26911
26912
26913 static int
26914 redisplay_mode_lines (Lisp_Object window, bool force)
26915 {
26916 int nwindows = 0;
26917
26918 while (!NILP (window))
26919 {
26920 struct window *w = XWINDOW (window);
26921
26922 if (WINDOWP (w->contents))
26923 nwindows += redisplay_mode_lines (w->contents, force);
26924 else if (force
26925 || FRAME_GARBAGED_P (XFRAME (w->frame))
26926 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26927 {
26928 struct text_pos lpoint;
26929 struct buffer *old = current_buffer;
26930
26931
26932 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26933 set_buffer_internal_1 (XBUFFER (w->contents));
26934
26935
26936
26937 if (!EQ (window, selected_window))
26938 {
26939 struct text_pos pt;
26940
26941 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26942 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26943 }
26944
26945
26946 clear_glyph_matrix (w->desired_matrix);
26947 if (display_mode_lines (w))
26948 ++nwindows;
26949
26950
26951 set_buffer_internal_1 (old);
26952 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26953 }
26954
26955 window = w->next;
26956 }
26957
26958 return nwindows;
26959 }
26960
26961
26962
26963
26964
26965
26966 static int
26967 display_mode_lines (struct window *w)
26968 {
26969 Lisp_Object old_selected_window = selected_window;
26970 Lisp_Object new_frame = w->frame;
26971 specpdl_ref count = SPECPDL_INDEX ();
26972 int n = 0;
26973
26974 record_unwind_protect (restore_selected_window, selected_window);
26975 record_unwind_protect
26976 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26977
26978 if (window_wants_mode_line (w))
26979 {
26980 Lisp_Object window;
26981 Lisp_Object default_help
26982 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26983
26984
26985
26986 XSETWINDOW (window, w);
26987 if (FUNCTIONP (default_help))
26988 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26989 else if (STRINGP (default_help))
26990 wset_mode_line_help_echo (w, default_help);
26991 else
26992 wset_mode_line_help_echo (w, Qnil);
26993 }
26994
26995 selected_frame = new_frame;
26996
26997
26998 XSETWINDOW (selected_window, w);
26999 XFRAME (new_frame)->selected_window = selected_window;
27000
27001
27002 line_number_displayed = false;
27003 w->column_number_displayed = -1;
27004
27005 if (window_wants_mode_line (w))
27006 {
27007 Lisp_Object window_mode_line_format
27008 = window_parameter (w, Qmode_line_format);
27009 struct window *sel_w = XWINDOW (old_selected_window);
27010
27011
27012 display_mode_line (w,
27013 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
27014 NILP (window_mode_line_format)
27015 ? BVAR (current_buffer, mode_line_format)
27016 : window_mode_line_format);
27017 ++n;
27018 }
27019
27020 if (window_wants_tab_line (w))
27021 {
27022 Lisp_Object window_tab_line_format
27023 = window_parameter (w, Qtab_line_format);
27024
27025 display_mode_line (w, TAB_LINE_FACE_ID,
27026 NILP (window_tab_line_format)
27027 ? BVAR (current_buffer, tab_line_format)
27028 : window_tab_line_format);
27029 ++n;
27030 }
27031
27032 if (window_wants_header_line (w))
27033 {
27034 Lisp_Object window_header_line_format
27035 = window_parameter (w, Qheader_line_format);
27036
27037 display_mode_line (w, HEADER_LINE_FACE_ID,
27038 NILP (window_header_line_format)
27039 ? BVAR (current_buffer, header_line_format)
27040 : window_header_line_format);
27041 ++n;
27042 }
27043
27044 unbind_to (count, Qnil);
27045
27046 if (n > 0)
27047 w->must_be_updated_p = true;
27048 return n;
27049 }
27050
27051
27052
27053
27054
27055
27056
27057
27058 static int
27059 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
27060 {
27061 struct it it;
27062 struct face *face;
27063 specpdl_ref count = SPECPDL_INDEX ();
27064
27065 init_iterator (&it, w, -1, -1, NULL, face_id);
27066
27067
27068 it.glyph_row->enabled_p = false;
27069 prepare_desired_row (w, it.glyph_row, true);
27070
27071 it.glyph_row->mode_line_p = true;
27072 if (face_id == TAB_LINE_FACE_ID)
27073 {
27074 it.glyph_row->tab_line_p = true;
27075 w->desired_matrix->tab_line_p = true;
27076 }
27077 else if (face_id == HEADER_LINE_FACE_ID)
27078 w->desired_matrix->header_line_p = true;
27079
27080
27081
27082
27083 it.paragraph_embedding = L2R;
27084
27085 record_unwind_protect (unwind_format_mode_line,
27086 format_mode_line_unwind_data (NULL, NULL,
27087 Qnil, false));
27088
27089
27090
27091
27092 push_kboard (FRAME_KBOARD (it.f));
27093 record_unwind_save_match_data ();
27094
27095 if (NILP (Vmode_line_compact)
27096 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
27097 {
27098 mode_line_target = MODE_LINE_DISPLAY;
27099 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27100 }
27101 else
27102 {
27103 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
27104 if (EQ (Vmode_line_compact, Qlong)
27105 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
27106 {
27107
27108
27109 display_string (NULL, mode_string, Qnil,
27110 0, 0, &it, 0, 0, 0,
27111 STRING_MULTIBYTE (mode_string));
27112 }
27113 else
27114 {
27115
27116 ptrdiff_t i = 0, i_byte = 0, start = 0;
27117 int prev = 0;
27118
27119 while (i < SCHARS (mode_string))
27120 {
27121 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
27122 if (c == ' ' && prev == ' ')
27123 {
27124 display_string (NULL,
27125 Fsubstring (mode_string, make_fixnum (start),
27126 make_fixnum (i - 1)),
27127 Qnil, 0, 0, &it, 0, 0, 0,
27128 STRING_MULTIBYTE (mode_string));
27129
27130 while (c == ' ' && i < SCHARS (mode_string))
27131 c = fetch_string_char_advance (mode_string, &i, &i_byte);
27132 start = i - 1;
27133 }
27134 prev = c;
27135 }
27136
27137
27138 if (start < i)
27139 display_string (NULL,
27140 Fsubstring (mode_string, make_fixnum (start),
27141 make_fixnum (i)),
27142 Qnil, 0, 0, &it, 0, 0, 0,
27143 STRING_MULTIBYTE (mode_string));
27144 }
27145 }
27146 pop_kboard ();
27147
27148 unbind_to (count, Qnil);
27149
27150
27151 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
27152
27153 compute_line_metrics (&it);
27154 it.glyph_row->full_width_p = true;
27155 it.glyph_row->continued_p = false;
27156 it.glyph_row->truncated_on_left_p = false;
27157 it.glyph_row->truncated_on_right_p = false;
27158
27159
27160 face = FACE_FROM_ID (it.f, face_id);
27161 extend_face_to_end_of_line (&it);
27162 if (face->box != FACE_NO_BOX)
27163 {
27164 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
27165 + it.glyph_row->used[TEXT_AREA] - 1);
27166 int box_thickness = face->box_vertical_line_width;
27167 last->right_box_line_p = true;
27168
27169
27170
27171
27172
27173
27174 if (box_thickness > 0)
27175 last->pixel_width += max (0, (box_thickness
27176 - (it.current_x - it.last_visible_x)));
27177 }
27178
27179 return it.glyph_row->height;
27180 }
27181
27182
27183
27184
27185 static Lisp_Object
27186 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
27187 {
27188 register Lisp_Object tail, prev;
27189 register Lisp_Object tem;
27190
27191 tail = list;
27192 prev = Qnil;
27193 while (CONSP (tail))
27194 {
27195 tem = XCAR (tail);
27196
27197 if (EQ (elt, tem))
27198 {
27199
27200 if (NILP (prev))
27201 list = XCDR (tail);
27202 else
27203 Fsetcdr (prev, XCDR (tail));
27204
27205
27206 Fsetcdr (tail, list);
27207 return tail;
27208 }
27209 else
27210 prev = tail;
27211 tail = XCDR (tail);
27212 maybe_quit ();
27213 }
27214
27215
27216 return list;
27217 }
27218
27219
27220
27221
27222
27223 static Lisp_Object
27224 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
27225 {
27226 eassert (nargs == 4);
27227 return Fset_text_properties (args[0], args[1], args[2], args[3]);
27228 }
27229
27230
27231
27232
27233
27234
27235
27236
27237
27238
27239
27240
27241
27242
27243
27244
27245
27246
27247
27248
27249
27250
27251
27252
27253
27254 static int
27255 display_mode_element (struct it *it, int depth, int field_width, int precision,
27256 Lisp_Object elt, Lisp_Object props, bool risky)
27257 {
27258 int n = 0, field, prec;
27259 bool literal = false;
27260
27261 tail_recurse:
27262 if (depth > 100)
27263 elt = build_string ("*too-deep*");
27264
27265 depth++;
27266
27267 switch (XTYPE (elt))
27268 {
27269 case Lisp_String:
27270 {
27271
27272 unsigned char c;
27273 ptrdiff_t offset = 0;
27274
27275 if (SCHARS (elt) > 0
27276 && (!NILP (props) || risky))
27277 {
27278 Lisp_Object oprops, aelt;
27279 oprops = Ftext_properties_at (make_fixnum (0), elt);
27280
27281
27282
27283
27284
27285 if (NILP (Fequal (props, oprops)) || risky)
27286 {
27287
27288
27289 if (! NILP (oprops) && !risky)
27290 {
27291 Lisp_Object tem;
27292
27293 oprops = Fcopy_sequence (oprops);
27294 tem = props;
27295 while (CONSP (tem))
27296 {
27297 oprops = plist_put (oprops, XCAR (tem),
27298 XCAR (XCDR (tem)));
27299 tem = XCDR (XCDR (tem));
27300 }
27301 props = oprops;
27302 }
27303
27304 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27305 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27306 {
27307
27308
27309 elt = XCAR (aelt);
27310 mode_line_proptrans_alist
27311 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27312 }
27313 else
27314 {
27315 Lisp_Object tem;
27316
27317
27318
27319 if (! NILP (aelt))
27320 mode_line_proptrans_alist
27321 = Fdelq (aelt, mode_line_proptrans_alist);
27322
27323 elt = Fcopy_sequence (elt);
27324
27325
27326
27327 internal_condition_case_n (safe_set_text_properties,
27328 4,
27329 ((Lisp_Object [])
27330 {make_fixnum (0),
27331 Flength (elt),
27332 props,
27333 elt}),
27334 Qt, safe_eval_handler);
27335
27336 mode_line_proptrans_alist
27337 = Fcons (Fcons (elt, props),
27338 mode_line_proptrans_alist);
27339
27340
27341 tem = Fnthcdr (make_fixnum (50),
27342 mode_line_proptrans_alist);
27343 if (! NILP (tem))
27344 XSETCDR (tem, Qnil);
27345 }
27346 }
27347 }
27348
27349 offset = 0;
27350
27351 if (literal)
27352 {
27353 prec = precision - n;
27354 switch (mode_line_target)
27355 {
27356 case MODE_LINE_NOPROP:
27357 case MODE_LINE_TITLE:
27358 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27359 break;
27360 case MODE_LINE_STRING:
27361 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27362 break;
27363 case MODE_LINE_DISPLAY:
27364 n += display_string (NULL, elt, Qnil, 0, 0, it,
27365 0, prec, 0, STRING_MULTIBYTE (elt));
27366 break;
27367 }
27368
27369 break;
27370 }
27371
27372
27373
27374 while ((precision <= 0 || n < precision)
27375 && SREF (elt, offset) != 0
27376 && (mode_line_target != MODE_LINE_DISPLAY
27377 || it->current_x < it->last_visible_x))
27378 {
27379 ptrdiff_t last_offset = offset;
27380
27381
27382 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27383 ;
27384
27385 if (offset - 1 != last_offset)
27386 {
27387 ptrdiff_t nchars, nbytes;
27388
27389
27390
27391
27392 offset--;
27393
27394 prec = c_string_width (SDATA (elt) + last_offset,
27395 offset - last_offset, precision - n,
27396 &nchars, &nbytes);
27397
27398 switch (mode_line_target)
27399 {
27400 case MODE_LINE_NOPROP:
27401 case MODE_LINE_TITLE:
27402 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27403 break;
27404 case MODE_LINE_STRING:
27405 {
27406 ptrdiff_t bytepos = last_offset;
27407 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27408 ptrdiff_t endpos = (precision <= 0
27409 ? string_byte_to_char (elt, offset)
27410 : charpos + nchars);
27411 Lisp_Object mode_string
27412 = Fsubstring (elt, make_fixnum (charpos),
27413 make_fixnum (endpos));
27414 n += store_mode_line_string (NULL, mode_string, false,
27415 0, 0, Qnil);
27416 }
27417 break;
27418 case MODE_LINE_DISPLAY:
27419 {
27420 ptrdiff_t bytepos = last_offset;
27421 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27422
27423 if (precision <= 0)
27424 nchars = string_byte_to_char (elt, offset) - charpos;
27425 n += display_string (NULL, elt, Qnil, 0, charpos,
27426 it, 0, nchars, 0,
27427 STRING_MULTIBYTE (elt));
27428 }
27429 break;
27430 }
27431 }
27432 else
27433 {
27434 ptrdiff_t percent_position = offset;
27435
27436
27437
27438 field = 0;
27439 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27440 field = field * 10 + c - '0';
27441
27442
27443 if (field_width - n > 0 && field > field_width - n)
27444 field = field_width - n;
27445
27446
27447 prec = precision - n;
27448
27449 if (c == 'M')
27450 n += display_mode_element (it, depth, field, prec,
27451 Vglobal_mode_string, props,
27452 risky);
27453 else if (c != 0)
27454 {
27455 bool multibyte;
27456 ptrdiff_t bytepos, charpos;
27457 const char *spec;
27458 Lisp_Object string;
27459
27460 bytepos = percent_position;
27461 charpos = (STRING_MULTIBYTE (elt)
27462 ? string_byte_to_char (elt, bytepos)
27463 : bytepos);
27464 spec = decode_mode_spec (it->w, c, field, &string);
27465 eassert (NILP (string) || STRINGP (string));
27466 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27467
27468
27469 ptrdiff_t nbytes = strlen (spec);
27470 ptrdiff_t nchars, mb_nbytes;
27471 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27472 &nchars, &mb_nbytes);
27473 if (!(nbytes == nchars || nbytes != mb_nbytes))
27474 multibyte = true;
27475
27476 switch (mode_line_target)
27477 {
27478 case MODE_LINE_NOPROP:
27479 case MODE_LINE_TITLE:
27480 n += store_mode_line_noprop (spec, field, prec);
27481 break;
27482 case MODE_LINE_STRING:
27483 {
27484 Lisp_Object tem = build_string (spec);
27485 props = Ftext_properties_at (make_fixnum (charpos), elt);
27486
27487 n += store_mode_line_string (NULL, tem, false,
27488 field, prec, props);
27489 }
27490 break;
27491 case MODE_LINE_DISPLAY:
27492 {
27493 int nglyphs_before, nwritten;
27494
27495 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27496 nwritten = display_string (spec, string, elt,
27497 charpos, 0, it,
27498 field, prec, 0,
27499 multibyte);
27500
27501
27502
27503
27504 if (nwritten > 0)
27505 {
27506 struct glyph *glyph
27507 = (it->glyph_row->glyphs[TEXT_AREA]
27508 + nglyphs_before);
27509 int i;
27510
27511 for (i = 0; i < nwritten; ++i)
27512 {
27513 glyph[i].object = elt;
27514 glyph[i].charpos = charpos;
27515 }
27516
27517 n += nwritten;
27518 }
27519 }
27520 break;
27521 }
27522 }
27523 else
27524 break;
27525 }
27526 }
27527 }
27528 break;
27529
27530 case Lisp_Symbol:
27531
27532
27533
27534
27535 {
27536 register Lisp_Object tem;
27537
27538
27539
27540 if (NILP (Fget (elt, Qrisky_local_variable)))
27541 risky = true;
27542
27543 tem = Fboundp (elt);
27544 if (!NILP (tem))
27545 {
27546 tem = Fsymbol_value (elt);
27547
27548
27549 if (STRINGP (tem))
27550 literal = true;
27551
27552 if (!EQ (tem, elt))
27553 {
27554
27555 elt = tem;
27556 goto tail_recurse;
27557 }
27558 }
27559 }
27560 break;
27561
27562 case Lisp_Cons:
27563 {
27564 register Lisp_Object car, tem;
27565
27566
27567
27568
27569
27570
27571
27572
27573
27574
27575 car = XCAR (elt);
27576 if (EQ (car, QCeval))
27577 {
27578
27579
27580
27581 if (risky)
27582 break;
27583
27584 if (CONSP (XCDR (elt)))
27585 {
27586 Lisp_Object spec;
27587 spec = safe__eval (true, XCAR (XCDR (elt)));
27588
27589
27590
27591
27592
27593
27594 if (!FRAME_LIVE_P (it->f))
27595 signal_error (":eval deleted the frame being displayed", elt);
27596 n += display_mode_element (it, depth, field_width - n,
27597 precision - n, spec, props,
27598 risky);
27599 }
27600 }
27601 else if (EQ (car, QCpropertize))
27602 {
27603
27604
27605
27606 if (risky)
27607 break;
27608
27609 if (CONSP (XCDR (elt)))
27610 n += display_mode_element (it, depth, field_width - n,
27611 precision - n, XCAR (XCDR (elt)),
27612 XCDR (XCDR (elt)), risky);
27613 }
27614 else if (SYMBOLP (car))
27615 {
27616 tem = Fboundp (car);
27617 elt = XCDR (elt);
27618 if (!CONSP (elt))
27619 goto invalid;
27620
27621
27622 if (!NILP (tem))
27623 {
27624 tem = Fsymbol_value (car);
27625 if (!NILP (tem))
27626 {
27627 elt = XCAR (elt);
27628 goto tail_recurse;
27629 }
27630 }
27631
27632
27633
27634 elt = XCDR (elt);
27635 if (NILP (elt))
27636 break;
27637 else if (!CONSP (elt))
27638 goto invalid;
27639 elt = XCAR (elt);
27640 goto tail_recurse;
27641 }
27642 else if (FIXNUMP (car))
27643 {
27644 register int lim = XFIXNUM (car);
27645 elt = XCDR (elt);
27646 if (lim < 0)
27647 {
27648
27649 if (precision <= 0)
27650 precision = -lim;
27651 else
27652 precision = min (precision, -lim);
27653 }
27654 else if (lim > 0)
27655 {
27656
27657
27658 if (precision > 0)
27659 lim = min (precision, lim);
27660
27661
27662
27663
27664 field_width = max (lim, field_width);
27665 }
27666 goto tail_recurse;
27667 }
27668 else if (STRINGP (car) || CONSP (car))
27669 FOR_EACH_TAIL_SAFE (elt)
27670 {
27671 if (0 < precision && precision <= n)
27672 break;
27673 n += display_mode_element (it, depth,
27674
27675
27676 (! CONSP (XCDR (elt))
27677 ? field_width - n
27678 : 0),
27679 precision - n, XCAR (elt),
27680 props, risky);
27681 }
27682 }
27683 break;
27684
27685 default:
27686 invalid:
27687 elt = build_string ("*invalid*");
27688 goto tail_recurse;
27689 }
27690
27691
27692 if (field_width > 0 && n < field_width)
27693 {
27694 switch (mode_line_target)
27695 {
27696 case MODE_LINE_NOPROP:
27697 case MODE_LINE_TITLE:
27698 n += store_mode_line_noprop ("", field_width - n, 0);
27699 break;
27700 case MODE_LINE_STRING:
27701 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27702 Qnil);
27703 break;
27704 case MODE_LINE_DISPLAY:
27705 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27706 0, 0, 0);
27707 break;
27708 }
27709 }
27710
27711 return n;
27712 }
27713
27714
27715
27716
27717
27718
27719
27720
27721
27722
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733 static int
27734 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27735 bool copy_string,
27736 int field_width, int precision, Lisp_Object props)
27737 {
27738 ptrdiff_t len;
27739 int n = 0;
27740
27741 if (string != NULL)
27742 {
27743 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27744 lisp_string = make_string (string, len);
27745 if (NILP (props))
27746 props = mode_line_string_face_prop;
27747 else if (!NILP (mode_line_string_face))
27748 {
27749 Lisp_Object face = plist_get (props, Qface);
27750 props = Fcopy_sequence (props);
27751 if (NILP (face))
27752 face = mode_line_string_face;
27753 else
27754 face = list2 (face, mode_line_string_face);
27755 props = plist_put (props, Qface, face);
27756 }
27757 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27758 props, lisp_string);
27759 }
27760 else
27761 {
27762 len = SCHARS (lisp_string);
27763 if (precision > 0 && len > precision)
27764 {
27765 len = precision;
27766 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27767 precision = -1;
27768 }
27769 if (!NILP (mode_line_string_face))
27770 {
27771 Lisp_Object face;
27772 if (NILP (props))
27773 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27774 face = plist_get (props, Qface);
27775 if (NILP (face))
27776 face = mode_line_string_face;
27777 else
27778 face = list2 (face, mode_line_string_face);
27779 props = list2 (Qface, face);
27780 if (copy_string)
27781 lisp_string = Fcopy_sequence (lisp_string);
27782 }
27783 if (!NILP (props))
27784 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27785 props, lisp_string);
27786 }
27787
27788 if (len > 0)
27789 {
27790 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27791 n += len;
27792 }
27793
27794 if (field_width > len)
27795 {
27796 field_width -= len;
27797 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27798 Qnil);
27799 if (!NILP (props))
27800 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27801 props, lisp_string);
27802 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27803 n += field_width;
27804 }
27805
27806 return n;
27807 }
27808
27809
27810 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27811 1, 4, 0,
27812 doc:
27813
27814
27815
27816
27817
27818
27819
27820
27821
27822
27823
27824
27825
27826
27827
27828 )
27829 (Lisp_Object format, Lisp_Object face,
27830 Lisp_Object window, Lisp_Object buffer)
27831 {
27832 struct it it;
27833 int len;
27834 struct window *w;
27835 struct buffer *old_buffer = NULL;
27836 int face_id;
27837 bool no_props = FIXNUMP (face);
27838 specpdl_ref count = SPECPDL_INDEX ();
27839 Lisp_Object str;
27840 int string_start = 0;
27841
27842 w = decode_any_window (window);
27843 XSETWINDOW (window, w);
27844
27845 if (NILP (buffer))
27846 buffer = w->contents;
27847 CHECK_BUFFER (buffer);
27848
27849
27850
27851 if (NILP (format) || noninteractive)
27852 return empty_unibyte_string;
27853
27854 if (no_props)
27855 face = Qnil;
27856
27857 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27858 : EQ (face, Qt) ? (EQ (window, selected_window)
27859 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27860 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27861 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27862 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27863 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27864 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27865 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27866 : DEFAULT_FACE_ID;
27867
27868 old_buffer = current_buffer;
27869
27870
27871
27872 record_unwind_protect (unwind_format_mode_line,
27873 format_mode_line_unwind_data
27874 (XFRAME (WINDOW_FRAME (w)),
27875 old_buffer, selected_window, true));
27876 mode_line_proptrans_alist = Qnil;
27877
27878 Fselect_window (window, Qt);
27879 set_buffer_internal_1 (XBUFFER (buffer));
27880
27881 init_iterator (&it, w, -1, -1, NULL, face_id);
27882
27883 if (no_props)
27884 {
27885 mode_line_target = MODE_LINE_NOPROP;
27886 mode_line_string_face_prop = Qnil;
27887 mode_line_string_list = Qnil;
27888 string_start = MODE_LINE_NOPROP_LEN (0);
27889 }
27890 else
27891 {
27892 mode_line_target = MODE_LINE_STRING;
27893 mode_line_string_list = Qnil;
27894 mode_line_string_face = face;
27895 mode_line_string_face_prop
27896 = NILP (face) ? Qnil : list2 (Qface, face);
27897 }
27898
27899 push_kboard (FRAME_KBOARD (it.f));
27900 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27901 pop_kboard ();
27902
27903 if (no_props)
27904 {
27905 len = MODE_LINE_NOPROP_LEN (string_start);
27906 str = make_string (mode_line_noprop_buf + string_start, len);
27907 }
27908 else
27909 {
27910 mode_line_string_list = Fnreverse (mode_line_string_list);
27911 str = Fmapconcat (Qidentity, mode_line_string_list,
27912 empty_unibyte_string);
27913 }
27914
27915 return unbind_to (count, str);
27916 }
27917
27918
27919
27920
27921 static void
27922 pint2str (register char *buf, register int width, register ptrdiff_t d)
27923 {
27924 register char *p = buf;
27925
27926 if (d <= 0)
27927 *p++ = '0';
27928 else
27929 {
27930 while (d > 0)
27931 {
27932 *p++ = d % 10 + '0';
27933 d /= 10;
27934 }
27935 }
27936
27937 for (width -= (int) (p - buf); width > 0; --width)
27938 *p++ = ' ';
27939 *p-- = '\0';
27940 while (p > buf)
27941 {
27942 d = *buf;
27943 *buf++ = *p;
27944 *p-- = d;
27945 }
27946 }
27947
27948
27949
27950
27951
27952 static const char power_letter[] =
27953 {
27954 0,
27955 'k',
27956 'M',
27957 'G',
27958 'T',
27959 'P',
27960 'E',
27961 'Z',
27962 'Y',
27963 'R',
27964 'Q'
27965 };
27966
27967 static void
27968 pint2hrstr (char *buf, int width, ptrdiff_t d)
27969 {
27970
27971
27972 ptrdiff_t quotient = d;
27973 int remainder = 0;
27974
27975 int tenths = -1;
27976 int exponent = 0;
27977
27978
27979 int length;
27980
27981 char * psuffix;
27982 char * p;
27983
27984 if (quotient >= 1000)
27985 {
27986
27987 do
27988 {
27989 remainder = quotient % 1000;
27990 quotient /= 1000;
27991 exponent++;
27992 }
27993 while (quotient >= 1000);
27994
27995
27996 if (quotient <= 9)
27997 {
27998 tenths = remainder / 100;
27999 if (remainder % 100 >= 50)
28000 {
28001 if (tenths < 9)
28002 tenths++;
28003 else
28004 {
28005 quotient++;
28006 if (quotient == 10)
28007 tenths = -1;
28008 else
28009 tenths = 0;
28010 }
28011 }
28012 }
28013 else
28014 if (remainder >= 500)
28015 {
28016 if (quotient < 999)
28017 quotient++;
28018 else
28019 {
28020 quotient = 1;
28021 exponent++;
28022 tenths = 0;
28023 }
28024 }
28025 }
28026
28027
28028 if (tenths == -1 && quotient <= 99)
28029 if (quotient <= 9)
28030 length = 1;
28031 else
28032 length = 2;
28033 else
28034 length = 3;
28035 p = psuffix = buf + max (width, length);
28036
28037
28038 *psuffix++ = power_letter[exponent];
28039 *psuffix = '\0';
28040
28041
28042 if (tenths >= 0)
28043 {
28044 *--p = '0' + tenths;
28045 *--p = '.';
28046 }
28047
28048
28049 do
28050 {
28051 int digit = quotient % 10;
28052 *--p = '0' + digit;
28053 }
28054 while ((quotient /= 10) != 0);
28055
28056
28057 while (buf < p)
28058 *--p = ' ';
28059 }
28060
28061
28062
28063
28064
28065 static unsigned char invalid_eol_type[] = "(*invalid*)";
28066
28067 static char *
28068 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
28069 {
28070 Lisp_Object val;
28071 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
28072 const unsigned char *eol_str;
28073 int eol_str_len;
28074
28075 Lisp_Object eoltype;
28076
28077 val = CODING_SYSTEM_SPEC (coding_system);
28078 eoltype = Qnil;
28079
28080 if (!VECTORP (val))
28081 {
28082 *buf++ = multibyte ? '-' : ' ';
28083 if (eol_flag)
28084 eoltype = eol_mnemonic_undecided;
28085
28086 }
28087 else
28088 {
28089 Lisp_Object attrs;
28090 Lisp_Object eolvalue;
28091
28092 attrs = AREF (val, 0);
28093 eolvalue = AREF (val, 2);
28094
28095 if (multibyte)
28096 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
28097 (unsigned char *) buf);
28098 else
28099 *buf++ = ' ';
28100
28101 if (eol_flag)
28102 {
28103
28104
28105 if (NILP (eolvalue))
28106 eoltype = eol_mnemonic_undecided;
28107 else if (VECTORP (eolvalue))
28108 eoltype = eol_mnemonic_undecided;
28109 else
28110 eoltype = (EQ (eolvalue, Qunix)
28111 ? eol_mnemonic_unix
28112 : EQ (eolvalue, Qdos)
28113 ? eol_mnemonic_dos : eol_mnemonic_mac);
28114 }
28115 }
28116
28117 if (eol_flag)
28118 {
28119
28120 if (STRINGP (eoltype))
28121 {
28122 eol_str = SDATA (eoltype);
28123 eol_str_len = SBYTES (eoltype);
28124 }
28125 else if (CHARACTERP (eoltype))
28126 {
28127 int c = XFIXNAT (eoltype);
28128 return buf + CHAR_STRING (c, (unsigned char *) buf);
28129 }
28130 else
28131 {
28132 eol_str = invalid_eol_type;
28133 eol_str_len = sizeof (invalid_eol_type) - 1;
28134 }
28135 memcpy (buf, eol_str, eol_str_len);
28136 buf += eol_str_len;
28137 }
28138
28139 return buf;
28140 }
28141
28142
28143
28144
28145 static int
28146 percent99 (ptrdiff_t n, ptrdiff_t d)
28147 {
28148 int percent = (d - 1 + 100.0 * n) / d;
28149 return min (percent, 99);
28150 }
28151
28152
28153
28154
28155
28156
28157
28158
28159
28160 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
28161
28162 static const char *
28163 decode_mode_spec (struct window *w, register int c, int field_width,
28164 Lisp_Object *string)
28165 {
28166 Lisp_Object obj;
28167 struct frame *f = XFRAME (WINDOW_FRAME (w));
28168 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
28169
28170
28171
28172
28173
28174 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
28175 struct buffer *b = current_buffer;
28176
28177 obj = Qnil;
28178 *string = Qnil;
28179
28180 switch (c)
28181 {
28182 case '*':
28183 if (!NILP (BVAR (b, read_only)))
28184 return "%";
28185 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28186 return "*";
28187 return "-";
28188
28189 case '+':
28190
28191 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28192 return "*";
28193 if (!NILP (BVAR (b, read_only)))
28194 return "%";
28195 return "-";
28196
28197 case '&':
28198
28199 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
28200 return "*";
28201 return "-";
28202
28203 case '%':
28204 return "%";
28205
28206 case '[':
28207 {
28208 int i;
28209 char *p;
28210
28211 if (command_loop_level > 5)
28212 return "[[[... ";
28213 p = decode_mode_spec_buf;
28214 for (i = 0; i < command_loop_level; i++)
28215 *p++ = '[';
28216 *p = 0;
28217 return decode_mode_spec_buf;
28218 }
28219
28220 case ']':
28221 {
28222 int i;
28223 char *p;
28224
28225 if (command_loop_level > 5)
28226 return " ...]]]";
28227 p = decode_mode_spec_buf;
28228 for (i = 0; i < command_loop_level; i++)
28229 *p++ = ']';
28230 *p = 0;
28231 return decode_mode_spec_buf;
28232 }
28233
28234 case '-':
28235 {
28236 register int i;
28237
28238
28239 if (mode_line_target == MODE_LINE_NOPROP
28240 || mode_line_target == MODE_LINE_STRING)
28241 return "--";
28242 if (field_width <= 0
28243 || field_width > sizeof (lots_of_dashes))
28244 {
28245 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28246 decode_mode_spec_buf[i] = '-';
28247 decode_mode_spec_buf[i] = '\0';
28248 return decode_mode_spec_buf;
28249 }
28250 else
28251 return lots_of_dashes;
28252 }
28253
28254 case 'b':
28255 obj = BVAR (b, name);
28256 break;
28257
28258 case 'c':
28259 case 'C':
28260
28261
28262
28263
28264
28265 if (mode_line_target == MODE_LINE_TITLE)
28266 return "";
28267 else
28268 {
28269 ptrdiff_t col = current_column ();
28270 int disp_col = (c == 'C') ? col + 1 : col;
28271 w->column_number_displayed = col;
28272 pint2str (decode_mode_spec_buf, width, disp_col);
28273 return decode_mode_spec_buf;
28274 }
28275
28276 case 'e':
28277 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28278 {
28279 if (NILP (Vmemory_full))
28280 return "";
28281 else
28282 return "!MEM FULL! ";
28283 }
28284 #else
28285 return "";
28286 #endif
28287
28288 case 'F':
28289
28290 if (!NILP (f->title))
28291 return SSDATA (f->title);
28292 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28293 return SSDATA (f->name);
28294 return "Emacs";
28295
28296 case 'f':
28297 obj = BVAR (b, filename);
28298 break;
28299
28300 case 'i':
28301 {
28302 ptrdiff_t size = ZV - BEGV;
28303 pint2str (decode_mode_spec_buf, width, size);
28304 return decode_mode_spec_buf;
28305 }
28306
28307 case 'I':
28308 {
28309 ptrdiff_t size = ZV - BEGV;
28310 pint2hrstr (decode_mode_spec_buf, width, size);
28311 return decode_mode_spec_buf;
28312 }
28313
28314 case 'l':
28315 {
28316 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28317 ptrdiff_t topline, nlines, height;
28318 ptrdiff_t junk;
28319
28320
28321 if (mode_line_target == MODE_LINE_TITLE)
28322 return "";
28323
28324 startpos = marker_position (w->start);
28325 startpos_byte = marker_byte_position (w->start);
28326 height = WINDOW_TOTAL_LINES (w);
28327
28328
28329
28330
28331
28332
28333
28334
28335 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28336 && startpos_byte <= BUF_ZV_BYTE (b)))
28337 {
28338 startpos = BUF_BEGV (b);
28339 startpos_byte = BUF_BEGV_BYTE (b);
28340 w->base_line_pos = 0;
28341 w->base_line_number = 0;
28342 }
28343
28344
28345
28346 if (w->base_line_pos == -1)
28347 goto no_value;
28348
28349
28350 if (FIXNUMP (Vline_number_display_limit)
28351 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28352 {
28353 w->base_line_pos = 0;
28354 w->base_line_number = 0;
28355 goto no_value;
28356 }
28357
28358 if (w->base_line_number > 0
28359 && w->base_line_pos > 0
28360 && w->base_line_pos <= startpos)
28361 {
28362 line = w->base_line_number;
28363 linepos = w->base_line_pos;
28364 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28365 }
28366 else
28367 {
28368 line = 1;
28369 linepos = BUF_BEGV (b);
28370 linepos_byte = BUF_BEGV_BYTE (b);
28371 }
28372
28373
28374 nlines = display_count_lines (linepos_byte,
28375 startpos_byte,
28376 startpos, &junk);
28377
28378 topline = nlines + line;
28379
28380
28381
28382
28383
28384 if (startpos == BUF_BEGV (b))
28385 {
28386 w->base_line_number = topline;
28387 w->base_line_pos = BUF_BEGV (b);
28388 }
28389 else if (nlines < height + 25 || nlines > height * 3 + 50
28390 || linepos == BUF_BEGV (b))
28391 {
28392 ptrdiff_t limit = BUF_BEGV (b);
28393 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28394 ptrdiff_t position;
28395 ptrdiff_t distance
28396 = (line_number_display_limit_width < 0 ? 0
28397 : ckd_mul (&distance, line_number_display_limit_width,
28398 height * 2 + 30)
28399 ? PTRDIFF_MAX : distance);
28400
28401 if (startpos - distance > limit)
28402 {
28403 limit = startpos - distance;
28404 limit_byte = CHAR_TO_BYTE (limit);
28405 }
28406
28407 nlines = display_count_lines (startpos_byte,
28408 limit_byte,
28409 - (height * 2 + 30),
28410 &position);
28411
28412
28413
28414 if (position == limit_byte && limit == startpos - distance)
28415 {
28416 w->base_line_pos = -1;
28417 w->base_line_number = 0;
28418 goto no_value;
28419 }
28420
28421 w->base_line_number = topline - nlines;
28422 w->base_line_pos = BYTE_TO_CHAR (position);
28423 }
28424
28425
28426 nlines = display_count_lines (startpos_byte,
28427 PT_BYTE, PT, &junk);
28428
28429
28430 line_number_displayed = true;
28431
28432
28433 pint2str (decode_mode_spec_buf, width, topline + nlines);
28434 return decode_mode_spec_buf;
28435 no_value:
28436 {
28437 char *p = decode_mode_spec_buf;
28438 int pad = width - 2;
28439 while (pad-- > 0)
28440 *p++ = ' ';
28441 *p++ = '?';
28442 *p++ = '?';
28443 *p = '\0';
28444 return decode_mode_spec_buf;
28445 }
28446 }
28447 break;
28448
28449 case 'm':
28450 obj = BVAR (b, mode_name);
28451 break;
28452
28453 case 'n':
28454 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28455 return " Narrow";
28456 break;
28457
28458
28459 case 'o':
28460 {
28461 ptrdiff_t toppos = marker_position (w->start);
28462 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28463 ptrdiff_t begv = BUF_BEGV (b);
28464 ptrdiff_t zv = BUF_ZV (b);
28465
28466 if (zv <= botpos)
28467 return toppos <= begv ? "All" : "Bottom";
28468 else if (toppos <= begv)
28469 return "Top";
28470 else
28471 {
28472 sprintf (decode_mode_spec_buf, "%2d%%",
28473 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28474 return decode_mode_spec_buf;
28475 }
28476 }
28477
28478
28479 case 'p':
28480 {
28481 ptrdiff_t pos = marker_position (w->start);
28482 ptrdiff_t begv = BUF_BEGV (b);
28483 ptrdiff_t zv = BUF_ZV (b);
28484
28485 if (w->window_end_pos <= BUF_Z (b) - zv)
28486 return pos <= begv ? "All" : "Bottom";
28487 else if (pos <= begv)
28488 return "Top";
28489 else
28490 {
28491 sprintf (decode_mode_spec_buf, "%2d%%",
28492 percent99 (pos - begv, zv - begv));
28493 return decode_mode_spec_buf;
28494 }
28495 }
28496
28497
28498 case 'P':
28499 {
28500 ptrdiff_t toppos = marker_position (w->start);
28501 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28502 ptrdiff_t begv = BUF_BEGV (b);
28503 ptrdiff_t zv = BUF_ZV (b);
28504
28505 if (zv <= botpos)
28506 return toppos <= begv ? "All" : "Bottom";
28507 else
28508 {
28509 sprintf (decode_mode_spec_buf,
28510 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28511 percent99 (botpos - begv, zv - begv));
28512 return decode_mode_spec_buf;
28513 }
28514 }
28515
28516
28517
28518 case 'q':
28519 {
28520 ptrdiff_t toppos = marker_position (w->start);
28521 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28522 ptrdiff_t begv = BUF_BEGV (b);
28523 ptrdiff_t zv = BUF_ZV (b);
28524 int top_perc, bot_perc;
28525
28526 if ((toppos <= begv) && (zv <= botpos))
28527 return "All ";
28528
28529 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28530 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28531
28532 if (top_perc == bot_perc)
28533 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28534 else
28535 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28536
28537 return decode_mode_spec_buf;
28538 }
28539
28540 case 's':
28541
28542 obj = Fget_buffer_process (Fcurrent_buffer ());
28543 if (NILP (obj))
28544 return "no process";
28545 #ifndef MSDOS
28546 obj = Fsymbol_name (Fprocess_status (obj));
28547 #endif
28548 break;
28549
28550 case '@':
28551 {
28552 specpdl_ref count = inhibit_garbage_collection ();
28553 Lisp_Object curdir = BVAR (current_buffer, directory);
28554 Lisp_Object val = Qnil;
28555
28556 if (STRINGP (curdir))
28557 val = safe_call1 (intern ("file-remote-p"), curdir);
28558
28559 val = unbind_to (count, val);
28560
28561 if (NILP (val))
28562 return "-";
28563 else
28564 return "@";
28565 }
28566
28567 case 'z':
28568
28569 case 'Z':
28570
28571 {
28572 bool eol_flag = (c == 'Z');
28573 char *p = decode_mode_spec_buf;
28574
28575 if (! FRAME_WINDOW_P (f))
28576 {
28577
28578
28579 p = decode_mode_spec_coding (CODING_ID_NAME
28580 (FRAME_KEYBOARD_CODING (f)->id),
28581 p, false);
28582 p = decode_mode_spec_coding (CODING_ID_NAME
28583 (FRAME_TERMINAL_CODING (f)->id),
28584 p, false);
28585 }
28586 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28587 p, eol_flag);
28588
28589 #if false
28590 #ifdef subprocesses
28591 obj = Fget_buffer_process (Fcurrent_buffer ());
28592 if (PROCESSP (obj))
28593 {
28594 p = decode_mode_spec_coding
28595 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28596 p = decode_mode_spec_coding
28597 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28598 }
28599 #endif
28600 #endif
28601 *p = 0;
28602 return decode_mode_spec_buf;
28603 }
28604 }
28605
28606 if (STRINGP (obj))
28607 {
28608 *string = obj;
28609 return SSDATA (obj);
28610 }
28611 else
28612 return "";
28613 }
28614
28615
28616
28617
28618 ptrdiff_t
28619 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28620 {
28621 ptrdiff_t ignored;
28622 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28623 }
28624
28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635 static ptrdiff_t
28636 display_count_lines (ptrdiff_t start_byte,
28637 ptrdiff_t limit_byte, ptrdiff_t count,
28638 ptrdiff_t *byte_pos_ptr)
28639 {
28640 register unsigned char *cursor;
28641 unsigned char *base;
28642
28643 register ptrdiff_t ceiling;
28644 register unsigned char *ceiling_addr;
28645 ptrdiff_t orig_count = count;
28646
28647
28648
28649 bool selective_display
28650 = (!NILP (BVAR (current_buffer, selective_display))
28651 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28652
28653 if (count > 0)
28654 {
28655 while (start_byte < limit_byte)
28656 {
28657 ceiling = BUFFER_CEILING_OF (start_byte);
28658 ceiling = min (limit_byte - 1, ceiling);
28659 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28660 base = (cursor = BYTE_POS_ADDR (start_byte));
28661
28662 do
28663 {
28664 if (selective_display)
28665 {
28666 while (*cursor != '\n' && *cursor != 015
28667 && ++cursor != ceiling_addr)
28668 continue;
28669 if (cursor == ceiling_addr)
28670 break;
28671 }
28672 else
28673 {
28674 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28675 if (! cursor)
28676 break;
28677 }
28678
28679 cursor++;
28680
28681 if (--count == 0)
28682 {
28683 start_byte += cursor - base;
28684 *byte_pos_ptr = start_byte;
28685 return orig_count;
28686 }
28687 }
28688 while (cursor < ceiling_addr);
28689
28690 start_byte += ceiling_addr - base;
28691 }
28692 }
28693 else
28694 {
28695 while (start_byte > limit_byte)
28696 {
28697 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28698 ceiling = max (limit_byte, ceiling);
28699 ceiling_addr = BYTE_POS_ADDR (ceiling);
28700 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28701 while (true)
28702 {
28703 if (selective_display)
28704 {
28705 while (--cursor >= ceiling_addr
28706 && *cursor != '\n' && *cursor != 015)
28707 continue;
28708 if (cursor < ceiling_addr)
28709 break;
28710 }
28711 else
28712 {
28713 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28714 if (! cursor)
28715 break;
28716 }
28717
28718 if (++count == 0)
28719 {
28720 start_byte += cursor - base + 1;
28721 *byte_pos_ptr = start_byte;
28722
28723
28724 return - orig_count - 1;
28725 }
28726 }
28727 start_byte += ceiling_addr - base;
28728 }
28729 }
28730
28731 *byte_pos_ptr = limit_byte;
28732
28733 if (count < 0)
28734 return - orig_count + count;
28735 return orig_count - count;
28736
28737 }
28738
28739
28740
28741
28742
28743
28744
28745
28746
28747
28748
28749
28750
28751
28752
28753
28754
28755
28756
28757
28758
28759
28760
28761
28762
28763
28764
28765
28766
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776
28777
28778
28779
28780
28781
28782
28783 static int
28784 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28785 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28786 int field_width, int precision, int max_x, int multibyte)
28787 {
28788 int hpos_at_start = it->hpos;
28789 int saved_face_id = it->face_id;
28790 struct glyph_row *row = it->glyph_row;
28791 ptrdiff_t it_charpos;
28792
28793
28794
28795 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28796 start, precision, field_width, multibyte);
28797
28798 if (string && STRINGP (lisp_string))
28799
28800
28801 it->stop_charpos = it->end_charpos;
28802
28803
28804
28805 if (STRINGP (face_string))
28806 {
28807 ptrdiff_t endptr;
28808 struct face *face;
28809
28810 it->face_id
28811 = face_at_string_position (it->w, face_string, face_string_pos,
28812 0, &endptr, it->base_face_id, false, 0);
28813 face = FACE_FROM_ID (it->f, it->face_id);
28814 it->face_box_p = face->box != FACE_NO_BOX;
28815
28816
28817
28818
28819 if (NILP (lisp_string))
28820 {
28821 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28822 face_string);
28823 if (!NILP (display))
28824 {
28825 Lisp_Object min_width = plist_get (display, Qmin_width);
28826 if (!NILP (min_width))
28827 display_min_width (it, 0, face_string, min_width);
28828 }
28829 }
28830 }
28831
28832
28833
28834 if (max_x <= 0)
28835 max_x = it->last_visible_x;
28836 else
28837 max_x = min (max_x, it->last_visible_x);
28838
28839
28840
28841 if (it->current_x < it->first_visible_x)
28842 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28843 MOVE_TO_POS | MOVE_TO_X);
28844
28845 row->ascent = it->max_ascent;
28846 row->height = it->max_ascent + it->max_descent;
28847 row->phys_ascent = it->max_phys_ascent;
28848 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28849 row->extra_line_spacing = it->max_extra_line_spacing;
28850
28851 if (STRINGP (it->string))
28852 it_charpos = IT_STRING_CHARPOS (*it);
28853 else
28854 it_charpos = IT_CHARPOS (*it);
28855
28856
28857
28858 while (it->current_x < max_x)
28859 {
28860 int x_before, x, n_glyphs_before, i, nglyphs;
28861
28862
28863 if (!get_next_display_element (it))
28864 break;
28865
28866
28867 x_before = it->current_x;
28868 n_glyphs_before = row->used[TEXT_AREA];
28869 PRODUCE_GLYPHS (it);
28870
28871 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28872 i = 0;
28873 x = x_before;
28874 while (i < nglyphs)
28875 {
28876 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28877
28878 if (it->line_wrap != TRUNCATE
28879 && x + glyph->pixel_width > max_x)
28880 {
28881
28882 if (CHAR_GLYPH_PADDING_P (*glyph))
28883 {
28884
28885 if (row->reversed_p)
28886 unproduce_glyphs (it, row->used[TEXT_AREA]
28887 - n_glyphs_before);
28888 row->used[TEXT_AREA] = n_glyphs_before;
28889 it->current_x = x_before;
28890 }
28891 else
28892 {
28893 if (row->reversed_p)
28894 unproduce_glyphs (it, row->used[TEXT_AREA]
28895 - (n_glyphs_before + i));
28896 row->used[TEXT_AREA] = n_glyphs_before + i;
28897 it->current_x = x;
28898 }
28899 break;
28900 }
28901 else if (x + glyph->pixel_width >= it->first_visible_x)
28902 {
28903
28904 ++it->hpos;
28905 if (x < it->first_visible_x)
28906 row->x = x - it->first_visible_x;
28907 }
28908 else
28909 {
28910
28911
28912 emacs_abort ();
28913 }
28914
28915 row->ascent = max (row->ascent, it->max_ascent);
28916 row->height = max (row->height, it->max_ascent + it->max_descent);
28917 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28918 row->phys_height = max (row->phys_height,
28919 it->max_phys_ascent + it->max_phys_descent);
28920 row->extra_line_spacing = max (row->extra_line_spacing,
28921 it->max_extra_line_spacing);
28922 x += glyph->pixel_width;
28923 ++i;
28924 }
28925
28926
28927 if (i < nglyphs)
28928 break;
28929
28930
28931 if (ITERATOR_AT_END_OF_LINE_P (it))
28932 {
28933 it->continuation_lines_width = 0;
28934 break;
28935 }
28936
28937 set_iterator_to_next (it, true);
28938 if (STRINGP (it->string))
28939 it_charpos = IT_STRING_CHARPOS (*it);
28940 else
28941 it_charpos = IT_CHARPOS (*it);
28942
28943
28944 if (it->line_wrap == TRUNCATE
28945 && it->current_x >= it->last_visible_x)
28946 {
28947
28948
28949
28950
28951
28952
28953 if (it_charpos <= it->string_nchars)
28954 {
28955 if (!FRAME_WINDOW_P (it->f))
28956 {
28957 int ii, n;
28958
28959 if (it->current_x > it->last_visible_x)
28960 {
28961
28962
28963 bool mode_line_p = false;
28964
28965
28966
28967 if (row->mode_line_p)
28968 {
28969 struct window *w = it->w;
28970 if (row == MATRIX_MODE_LINE_ROW (w->desired_matrix))
28971 mode_line_p = true;
28972 }
28973 if (!row->reversed_p)
28974 {
28975 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28976 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28977 break;
28978 }
28979 else
28980 {
28981 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28982 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28983 break;
28984 unproduce_glyphs (it, ii + 1);
28985 ii = row->used[TEXT_AREA] - (ii + 1);
28986 }
28987 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28988 {
28989 row->used[TEXT_AREA] = ii;
28990 if (row->mode_line_p)
28991 pad_mode_line (it, mode_line_p);
28992 else
28993 produce_special_glyphs (it, IT_TRUNCATION);
28994 }
28995 }
28996 produce_special_glyphs (it, IT_TRUNCATION);
28997 }
28998 row->truncated_on_right_p = true;
28999 }
29000 break;
29001 }
29002 }
29003
29004
29005 if (it->first_visible_x
29006 && it_charpos > 0)
29007 {
29008 if (!FRAME_WINDOW_P (it->f)
29009 || (row->reversed_p
29010 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29011 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
29012 insert_left_trunc_glyphs (it);
29013 row->truncated_on_left_p = true;
29014 }
29015
29016 it->face_id = saved_face_id;
29017
29018
29019 return it->hpos - hpos_at_start;
29020 }
29021
29022
29023
29024
29025
29026
29027
29028
29029
29030
29031
29032 int
29033 invisible_prop (Lisp_Object propval, Lisp_Object list)
29034 {
29035 Lisp_Object tail, proptail;
29036
29037 for (tail = list; CONSP (tail); tail = XCDR (tail))
29038 {
29039 register Lisp_Object tem;
29040 tem = XCAR (tail);
29041 if (EQ (propval, tem))
29042 return 1;
29043 if (CONSP (tem) && EQ (propval, XCAR (tem)))
29044 return NILP (XCDR (tem)) ? 1 : 2;
29045 }
29046
29047 if (CONSP (propval))
29048 {
29049 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
29050 {
29051 Lisp_Object propelt;
29052 propelt = XCAR (proptail);
29053 for (tail = list; CONSP (tail); tail = XCDR (tail))
29054 {
29055 register Lisp_Object tem;
29056 tem = XCAR (tail);
29057 if (EQ (propelt, tem))
29058 return 1;
29059 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
29060 return NILP (XCDR (tem)) ? 1 : 2;
29061 }
29062 }
29063 }
29064
29065 return 0;
29066 }
29067
29068 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
29069 doc:
29070
29071
29072
29073
29074
29075
29076
29077
29078
29079
29080
29081 )
29082 (Lisp_Object pos)
29083 {
29084 Lisp_Object prop
29085 = (FIXNATP (pos) || MARKERP (pos)
29086 ? Fget_char_property (pos, Qinvisible, Qnil)
29087 : pos);
29088 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
29089 return (invis == 0 ? Qnil
29090 : invis == 1 ? Qt
29091 : make_fixnum (invis));
29092 }
29093
29094
29095
29096
29097
29098
29099
29100
29101
29102
29103
29104
29105
29106
29107
29108
29109
29110
29111
29112
29113
29114
29115
29116
29117
29118
29119
29120
29121
29122
29123
29124
29125
29126
29127
29128
29129
29130
29131
29132
29133
29134
29135
29136
29137
29138
29139
29140
29141
29142
29143
29144
29145
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157
29158
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170
29171
29172
29173
29174 static bool
29175 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
29176 struct font *font, bool width_p, int *align_to)
29177 {
29178
29179
29180
29181
29182 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
29183 double pixels;
29184
29185 # define OK_PIXELS(val) (*res = (val), true)
29186 # define OK_ALIGN_TO(val) (*align_to = (val), true)
29187
29188 if (NILP (prop))
29189 return OK_PIXELS (0);
29190
29191 eassert (FRAME_LIVE_P (it->f));
29192
29193 if (SYMBOLP (prop))
29194 {
29195 if (SCHARS (SYMBOL_NAME (prop)) == 2)
29196 {
29197 char *unit = SSDATA (SYMBOL_NAME (prop));
29198
29199
29200 if (unit[0] == 'i' && unit[1] == 'n')
29201 pixels = 1.0;
29202 else if (unit[0] == 'm' && unit[1] == 'm')
29203 pixels = 25.4;
29204 else if (unit[0] == 'c' && unit[1] == 'm')
29205 pixels = 2.54;
29206 else
29207 pixels = 0;
29208 if (pixels > 0)
29209 {
29210 double ppi = (width_p ? FRAME_RES_X (it->f)
29211 : FRAME_RES_Y (it->f));
29212
29213 if (ppi > 0)
29214 return OK_PIXELS (ppi / pixels);
29215 return false;
29216 }
29217 }
29218
29219 #ifdef HAVE_WINDOW_SYSTEM
29220
29221 if (EQ (prop, Qheight))
29222 return OK_PIXELS (font
29223 ? normal_char_height (font, -1)
29224 : FRAME_LINE_HEIGHT (it->f));
29225
29226 if (EQ (prop, Qwidth))
29227 return OK_PIXELS (font
29228 ? FONT_WIDTH (font)
29229 : FRAME_COLUMN_WIDTH (it->f));
29230 #else
29231 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
29232 return OK_PIXELS (1);
29233 #endif
29234
29235
29236 if (EQ (prop, Qtext))
29237 return OK_PIXELS (width_p
29238 ? (window_box_width (it->w, TEXT_AREA)
29239 - lnum_pixel_width)
29240 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
29241
29242
29243
29244
29245 if (align_to && *align_to < 0)
29246 {
29247 *res = 0;
29248
29249 if (EQ (prop, Qleft))
29250 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29251 + lnum_pixel_width);
29252
29253 if (EQ (prop, Qright))
29254 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
29255
29256 if (EQ (prop, Qcenter))
29257 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29258 + lnum_pixel_width
29259 + window_box_width (it->w, TEXT_AREA) / 2);
29260
29261 if (EQ (prop, Qleft_fringe))
29262 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29263 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29264 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29265
29266 if (EQ (prop, Qright_fringe))
29267 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29268 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29269 : window_box_right_offset (it->w, TEXT_AREA));
29270
29271 if (EQ (prop, Qleft_margin))
29272 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29273
29274 if (EQ (prop, Qright_margin))
29275 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29276
29277 if (EQ (prop, Qscroll_bar))
29278 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29279 ? 0
29280 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29281 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29282 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29283 : 0)));
29284 }
29285 else
29286 {
29287
29288 if (EQ (prop, Qleft_fringe))
29289 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29290 if (EQ (prop, Qright_fringe))
29291 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29292 if (EQ (prop, Qleft_margin))
29293 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29294 if (EQ (prop, Qright_margin))
29295 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29296 if (EQ (prop, Qscroll_bar))
29297 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29298 }
29299
29300 prop = buffer_local_value (prop, it->w->contents);
29301 if (BASE_EQ (prop, Qunbound))
29302 prop = Qnil;
29303 }
29304
29305 if (NUMBERP (prop))
29306 {
29307 int base_unit = (width_p
29308 ? FRAME_COLUMN_WIDTH (it->f)
29309 : FRAME_LINE_HEIGHT (it->f));
29310 if (width_p && align_to && *align_to < 0)
29311 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29312 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29313 }
29314
29315 if (CONSP (prop))
29316 {
29317 Lisp_Object car = XCAR (prop);
29318 Lisp_Object cdr = XCDR (prop);
29319
29320 if (SYMBOLP (car))
29321 {
29322 #ifdef HAVE_WINDOW_SYSTEM
29323
29324 if (FRAME_WINDOW_P (it->f)
29325 && valid_image_p (prop))
29326 {
29327 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29328 struct image *img = IMAGE_FROM_ID (it->f, id);
29329
29330 return OK_PIXELS (width_p ? img->width : img->height);
29331 }
29332
29333 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29334 {
29335
29336 return OK_PIXELS (100);
29337 }
29338 #endif
29339
29340
29341 if (EQ (car, Qplus) || EQ (car, Qminus))
29342 {
29343 bool first = true;
29344 double px;
29345
29346 pixels = 0;
29347 while (CONSP (cdr))
29348 {
29349 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29350 font, width_p, align_to))
29351 return false;
29352 if (first)
29353 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29354 else
29355 pixels += px;
29356 cdr = XCDR (cdr);
29357 }
29358 if (EQ (car, Qminus))
29359 pixels = -pixels;
29360 return OK_PIXELS (pixels);
29361 }
29362
29363 car = buffer_local_value (car, it->w->contents);
29364 if (BASE_EQ (car, Qunbound))
29365 car = Qnil;
29366 }
29367
29368
29369 if (NUMBERP (car))
29370 {
29371 double fact;
29372 int offset =
29373 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29374 pixels = XFLOATINT (car);
29375 if (NILP (cdr))
29376 return OK_PIXELS (pixels + offset);
29377 if (calc_pixel_width_or_height (&fact, it, cdr,
29378 font, width_p, align_to))
29379 return OK_PIXELS (pixels * fact + offset);
29380 return false;
29381 }
29382
29383 return false;
29384 }
29385
29386 return false;
29387 }
29388
29389 void
29390 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29391 {
29392 #ifdef HAVE_WINDOW_SYSTEM
29393 normal_char_ascent_descent (font, -1, ascent, descent);
29394 #else
29395 *ascent = 1;
29396 *descent = 0;
29397 #endif
29398 }
29399
29400
29401
29402
29403
29404
29405 #ifdef HAVE_WINDOW_SYSTEM
29406
29407 #ifdef GLYPH_DEBUG
29408
29409 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29410 void
29411 dump_glyph_string (struct glyph_string *s)
29412 {
29413 fputs ("glyph string\n", stderr);
29414 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29415 s->x, s->y, s->width, s->height);
29416 fprintf (stderr, " ybase = %d\n", s->ybase);
29417 fprintf (stderr, " hl = %u\n", s->hl);
29418 fprintf (stderr, " left overhang = %d, right = %d\n",
29419 s->left_overhang, s->right_overhang);
29420 fprintf (stderr, " nchars = %d\n", s->nchars);
29421 fprintf (stderr, " extends to end of line = %d\n",
29422 s->extends_to_end_of_line_p);
29423 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29424 fprintf (stderr, " bg width = %d\n", s->background_width);
29425 }
29426
29427 #endif
29428
29429
29430
29431
29432
29433
29434
29435
29436
29437 #ifdef HAVE_NTGUI
29438
29439
29440
29441
29442
29443 # define ALLOCATE_HDC(hdc, f) \
29444 Lisp_Object prev_quit = Vinhibit_quit; \
29445 Vinhibit_quit = Qt; \
29446 HDC hdc = get_frame_dc ((f))
29447 # define RELEASE_HDC(hdc, f) \
29448 release_frame_dc ((f), (hdc)); \
29449 Vinhibit_quit = prev_quit
29450 #else
29451 # define ALLOCATE_HDC(hdc, f)
29452 # define RELEASE_HDC(hdc, f)
29453 #endif
29454
29455 static void
29456 init_glyph_string (struct glyph_string *s,
29457 #ifdef HAVE_NTGUI
29458 HDC hdc,
29459 #endif
29460 unsigned *char2b, struct window *w, struct glyph_row *row,
29461 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29462 {
29463 memset (s, 0, sizeof *s);
29464 s->w = w;
29465 s->f = XFRAME (w->frame);
29466 #ifdef HAVE_NTGUI
29467 s->hdc = hdc;
29468 #endif
29469 s->char2b = char2b;
29470 s->hl = hl;
29471 s->row = row;
29472 s->area = area;
29473 s->first_glyph = row->glyphs[area] + start;
29474 s->height = row->height;
29475 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29476 s->ybase = s->y + row->ascent;
29477 }
29478
29479
29480
29481
29482
29483 static void
29484 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29485 struct glyph_string *h, struct glyph_string *t)
29486 {
29487 if (h)
29488 {
29489 if (*head)
29490 (*tail)->next = h;
29491 else
29492 *head = h;
29493 h->prev = *tail;
29494 *tail = t;
29495 }
29496 }
29497
29498
29499
29500
29501
29502
29503 static void
29504 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29505 struct glyph_string *h, struct glyph_string *t)
29506 {
29507 if (h)
29508 {
29509 if (*head)
29510 (*head)->prev = t;
29511 else
29512 *tail = t;
29513 t->next = *head;
29514 *head = h;
29515 }
29516 }
29517
29518
29519
29520
29521
29522 static void
29523 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29524 struct glyph_string *s)
29525 {
29526 s->next = s->prev = NULL;
29527 append_glyph_string_lists (head, tail, s, s);
29528 }
29529
29530
29531
29532
29533
29534
29535
29536
29537 static struct face *
29538 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29539 unsigned *char2b, bool display_p)
29540 {
29541 struct face *face = FACE_FROM_ID (f, face_id);
29542 unsigned code = 0;
29543
29544 if (face->font)
29545 {
29546 code = face->font->driver->encode_char (face->font, c);
29547
29548 if (code == FONT_INVALID_CODE)
29549 code = 0;
29550 }
29551
29552 *char2b = code & 0xFFFF;
29553
29554
29555 #ifdef HAVE_X_WINDOWS
29556 if (display_p)
29557 #endif
29558 {
29559 eassert (face != NULL);
29560 prepare_face_for_display (f, face);
29561 }
29562
29563 return face;
29564 }
29565
29566
29567
29568
29569
29570
29571 static struct face *
29572 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29573 unsigned *char2b)
29574 {
29575 struct face *face;
29576 unsigned code = 0;
29577
29578 eassert (glyph->type == CHAR_GLYPH);
29579 face = FACE_FROM_ID (f, glyph->face_id);
29580
29581
29582 prepare_face_for_display (f, face);
29583
29584 if (face->font)
29585 {
29586 if (CHAR_BYTE8_P (glyph->u.ch))
29587 code = CHAR_TO_BYTE8 (glyph->u.ch);
29588 else
29589 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29590
29591 if (code == FONT_INVALID_CODE)
29592 code = 0;
29593 }
29594
29595
29596 *char2b = code & 0xFFFF;
29597 return face;
29598 }
29599
29600
29601
29602
29603
29604 static bool
29605 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29606 {
29607 unsigned code;
29608
29609 if (CHAR_BYTE8_P (c))
29610 code = CHAR_TO_BYTE8 (c);
29611 else
29612 code = font->driver->encode_char (font, c);
29613
29614 if (code == FONT_INVALID_CODE)
29615 return false;
29616
29617
29618 *char2b = code & 0xFFFF;
29619 return true;
29620 }
29621
29622
29623
29624
29625
29626
29627
29628
29629
29630
29631
29632
29633 static int
29634 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29635 int overlaps)
29636 {
29637 int i;
29638
29639
29640
29641 struct face *face;
29642
29643 eassert (s);
29644
29645 s->for_overlaps = overlaps;
29646 s->face = NULL;
29647 s->font = NULL;
29648 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29649 {
29650 int c = COMPOSITION_GLYPH (s->cmp, i);
29651
29652
29653
29654 if (c != '\t')
29655 {
29656 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29657 -1, Qnil);
29658
29659 face = get_char_face_and_encoding (s->f, c, face_id,
29660 s->char2b + i, true);
29661 if (face)
29662 {
29663 if (! s->face)
29664 {
29665 s->face = face;
29666 s->font = s->face->font;
29667 }
29668 else if (s->face != face)
29669 break;
29670 }
29671 }
29672 ++s->nchars;
29673 }
29674 s->cmp_to = i;
29675
29676 if (s->face == NULL)
29677 {
29678 s->face = base_face->ascii_face;
29679 s->font = s->face->font;
29680 }
29681
29682 if (s->hl == DRAW_MOUSE_FACE
29683 || (s->hl == DRAW_CURSOR
29684 && MATRIX_ROW (s->w->current_matrix,
29685 s->w->phys_cursor.vpos)->mouse_face_p
29686 && cursor_in_mouse_face_p (s->w)))
29687 {
29688 int c = COMPOSITION_GLYPH (s->cmp, 0);
29689 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29690 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29691 if (!s->face)
29692 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29693
29694 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29695 prepare_face_for_display (s->f, s->face);
29696 }
29697
29698
29699
29700 s->width = s->first_glyph->pixel_width;
29701
29702
29703
29704
29705
29706 if (s->font == NULL)
29707 {
29708 s->font_not_found_p = true;
29709 s->font = FRAME_FONT (s->f);
29710 }
29711
29712
29713 s->ybase += s->first_glyph->voffset;
29714
29715 return s->cmp_to;
29716 }
29717
29718 static int
29719 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29720 int start, int end, int overlaps)
29721 {
29722 struct glyph *glyph, *last;
29723 int voffset;
29724 Lisp_Object lgstring;
29725 int i;
29726 bool glyph_not_available_p;
29727
29728 s->for_overlaps = overlaps;
29729 glyph = s->row->glyphs[s->area] + start;
29730 last = s->row->glyphs[s->area] + end;
29731 voffset = glyph->voffset;
29732 glyph_not_available_p = glyph->glyph_not_available_p;
29733 s->cmp_id = glyph->u.cmp.id;
29734 s->cmp_from = glyph->slice.cmp.from;
29735 s->cmp_to = glyph->slice.cmp.to + 1;
29736 if (s->hl == DRAW_MOUSE_FACE
29737 || (s->hl == DRAW_CURSOR
29738 && MATRIX_ROW (s->w->current_matrix,
29739 s->w->phys_cursor.vpos)->mouse_face_p
29740 && cursor_in_mouse_face_p (s->w)))
29741 {
29742 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29743 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29744 if (!s->face)
29745 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29746 prepare_face_for_display (s->f, s->face);
29747 }
29748 else
29749 s->face = FACE_FROM_ID (s->f, face_id);
29750 lgstring = composition_gstring_from_id (s->cmp_id);
29751 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29752
29753
29754 s->width = s->first_glyph->pixel_width;
29755 glyph++;
29756 while (glyph < last
29757 && glyph->u.cmp.automatic
29758 && glyph->u.cmp.id == s->cmp_id
29759 && glyph->face_id == face_id
29760 && s->cmp_to == glyph->slice.cmp.from
29761 && glyph->glyph_not_available_p == glyph_not_available_p)
29762 {
29763 s->width += glyph->pixel_width;
29764 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29765 }
29766
29767 for (i = s->cmp_from; i < s->cmp_to; i++)
29768 {
29769 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29770 unsigned code = LGLYPH_CODE (lglyph);
29771
29772
29773 s->char2b[i] = code & 0xFFFF;
29774 }
29775
29776
29777
29778
29779 if (glyph_not_available_p)
29780 s->font_not_found_p = true;
29781
29782
29783 s->ybase += voffset;
29784
29785 return glyph - s->row->glyphs[s->area];
29786 }
29787
29788
29789
29790
29791
29792
29793
29794 static int
29795 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29796 int start, int end, int overlaps)
29797 {
29798 struct glyph *glyph, *last;
29799 int voffset;
29800
29801 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29802 s->for_overlaps = overlaps;
29803 glyph = s->row->glyphs[s->area] + start;
29804 last = s->row->glyphs[s->area] + end;
29805 voffset = glyph->voffset;
29806 s->face = FACE_FROM_ID (s->f, face_id);
29807 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29808 if (s->hl == DRAW_MOUSE_FACE
29809 || (s->hl == DRAW_CURSOR
29810 && MATRIX_ROW (s->w->current_matrix,
29811 s->w->phys_cursor.vpos)->mouse_face_p
29812 && cursor_in_mouse_face_p (s->w)))
29813 {
29814 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29815 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29816 if (!s->face)
29817 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29818 prepare_face_for_display (s->f, s->face);
29819 }
29820 s->nchars = 1;
29821 s->width = glyph->pixel_width;
29822 glyph++;
29823 while (glyph < last
29824 && glyph->type == GLYPHLESS_GLYPH
29825 && glyph->voffset == voffset
29826 && glyph->face_id == face_id)
29827 {
29828 s->nchars++;
29829 s->width += glyph->pixel_width;
29830 glyph++;
29831 }
29832 s->ybase += voffset;
29833 return glyph - s->row->glyphs[s->area];
29834 }
29835
29836
29837
29838
29839
29840
29841
29842
29843
29844
29845
29846 static int
29847 fill_glyph_string (struct glyph_string *s, int face_id,
29848 int start, int end, int overlaps)
29849 {
29850 struct glyph *glyph, *last;
29851 int voffset;
29852 bool glyph_not_available_p;
29853
29854 eassert (s->f == XFRAME (s->w->frame));
29855 eassert (s->nchars == 0);
29856 eassert (start >= 0 && end > start);
29857
29858 s->for_overlaps = overlaps;
29859 glyph = s->row->glyphs[s->area] + start;
29860 last = s->row->glyphs[s->area] + end;
29861 voffset = glyph->voffset;
29862 s->padding_p = glyph->padding_p;
29863 glyph_not_available_p = glyph->glyph_not_available_p;
29864
29865 while (glyph < last
29866 && glyph->type == CHAR_GLYPH
29867 && glyph->voffset == voffset
29868
29869 && glyph->face_id == face_id
29870 && glyph->glyph_not_available_p == glyph_not_available_p)
29871 {
29872 s->face = get_glyph_face_and_encoding (s->f, glyph,
29873 s->char2b + s->nchars);
29874 ++s->nchars;
29875 eassert (s->nchars <= end - start);
29876 s->width += glyph->pixel_width;
29877 if (glyph++->padding_p != s->padding_p)
29878 break;
29879 }
29880
29881 s->font = s->face->font;
29882
29883 if (s->hl == DRAW_MOUSE_FACE
29884 || (s->hl == DRAW_CURSOR
29885 && MATRIX_ROW (s->w->current_matrix,
29886 s->w->phys_cursor.vpos)->mouse_face_p
29887 && cursor_in_mouse_face_p (s->w)))
29888 {
29889 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29890 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29891 if (!s->face)
29892 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29893 s->face
29894 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29895 s->first_glyph->u.ch, -1, Qnil));
29896 prepare_face_for_display (s->f, s->face);
29897 }
29898
29899
29900
29901
29902
29903 if (s->font == NULL || glyph_not_available_p)
29904 {
29905 s->font_not_found_p = true;
29906 s->font = FRAME_FONT (s->f);
29907 }
29908
29909
29910 s->ybase += voffset;
29911
29912 eassert (s->face && s->face->gc);
29913 return glyph - s->row->glyphs[s->area];
29914 }
29915
29916
29917
29918
29919 static void
29920 fill_image_glyph_string (struct glyph_string *s)
29921 {
29922 eassert (s->first_glyph->type == IMAGE_GLYPH);
29923 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29924 eassert (s->img);
29925 s->slice = s->first_glyph->slice.img;
29926 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29927 s->font = s->face->font;
29928 if (s->hl == DRAW_MOUSE_FACE
29929 || (s->hl == DRAW_CURSOR
29930 && MATRIX_ROW (s->w->current_matrix,
29931 s->w->phys_cursor.vpos)->mouse_face_p
29932 && cursor_in_mouse_face_p (s->w)))
29933 {
29934 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29935 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29936 if (!s->face)
29937 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29938 prepare_face_for_display (s->f, s->face);
29939 }
29940 s->width = s->first_glyph->pixel_width;
29941
29942
29943 s->ybase += s->first_glyph->voffset;
29944 }
29945
29946
29947 #ifdef HAVE_XWIDGETS
29948 static void
29949 fill_xwidget_glyph_string (struct glyph_string *s)
29950 {
29951 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29952 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29953 s->font = s->face->font;
29954 if (s->hl == DRAW_MOUSE_FACE
29955 || (s->hl == DRAW_CURSOR
29956 && MATRIX_ROW (s->w->current_matrix,
29957 s->w->phys_cursor.vpos)->mouse_face_p
29958 && cursor_in_mouse_face_p (s->w)))
29959 {
29960 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29961 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29962 if (!s->face)
29963 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29964 prepare_face_for_display (s->f, s->face);
29965 }
29966 s->width = s->first_glyph->pixel_width;
29967 s->ybase += s->first_glyph->voffset;
29968 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29969 }
29970 #endif
29971
29972
29973
29974
29975
29976
29977
29978 static int
29979 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29980 {
29981 struct glyph *glyph, *last;
29982 int voffset, face_id;
29983
29984 eassert (s->first_glyph->type == STRETCH_GLYPH);
29985
29986 glyph = s->row->glyphs[s->area] + start;
29987 last = s->row->glyphs[s->area] + end;
29988 face_id = glyph->face_id;
29989 s->face = FACE_FROM_ID (s->f, face_id);
29990 s->font = s->face->font;
29991 if (s->hl == DRAW_MOUSE_FACE
29992 || (s->hl == DRAW_CURSOR
29993 && MATRIX_ROW (s->w->current_matrix,
29994 s->w->phys_cursor.vpos)->mouse_face_p
29995 && cursor_in_mouse_face_p (s->w)))
29996 {
29997 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29998 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29999 if (!s->face)
30000 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
30001 prepare_face_for_display (s->f, s->face);
30002 }
30003 s->width = glyph->pixel_width;
30004 s->nchars = 1;
30005 voffset = glyph->voffset;
30006
30007 for (++glyph;
30008 (glyph < last
30009 && glyph->type == STRETCH_GLYPH
30010 && glyph->voffset == voffset
30011 && glyph->face_id == face_id);
30012 ++glyph)
30013 s->width += glyph->pixel_width;
30014
30015
30016 s->ybase += voffset;
30017
30018
30019
30020 eassert (s->face);
30021 return glyph - s->row->glyphs[s->area];
30022 }
30023
30024 static struct font_metrics *
30025 get_per_char_metric (struct font *font, const unsigned *char2b)
30026 {
30027 static struct font_metrics metrics;
30028
30029 if (! font)
30030 return NULL;
30031 if (*char2b == FONT_INVALID_CODE)
30032 return NULL;
30033
30034 font->driver->text_extents (font, char2b, 1, &metrics);
30035 return &metrics;
30036 }
30037
30038
30039
30040
30041
30042
30043
30044 static void
30045 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
30046 {
30047 *ascent = FONT_BASE (font);
30048 *descent = FONT_DESCENT (font);
30049
30050 if (FONT_TOO_HIGH (font))
30051 {
30052 unsigned char2b;
30053
30054
30055
30056 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
30057 {
30058 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
30059 eassume (pcm);
30060
30061 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
30062 {
30063
30064
30065
30066 *ascent = pcm->ascent + 1;
30067 *descent = pcm->descent + 1;
30068 }
30069 }
30070 }
30071 }
30072
30073
30074
30075
30076
30077
30078 static int
30079 normal_char_height (struct font *font, int c)
30080 {
30081 int ascent, descent;
30082
30083 normal_char_ascent_descent (font, c, &ascent, &descent);
30084
30085 return ascent + descent;
30086 }
30087
30088
30089
30090
30091
30092
30093 void
30094 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
30095 {
30096 *left = *right = 0;
30097
30098 if (glyph->type == CHAR_GLYPH)
30099 {
30100 unsigned char2b;
30101 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
30102 if (face->font)
30103 {
30104 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
30105 if (pcm)
30106 {
30107 if (pcm->rbearing > pcm->width)
30108 *right = pcm->rbearing - pcm->width;
30109 if (pcm->lbearing < 0)
30110 *left = -pcm->lbearing;
30111 }
30112 }
30113 }
30114 else if (glyph->type == COMPOSITE_GLYPH)
30115 {
30116 if (! glyph->u.cmp.automatic)
30117 {
30118 struct composition *cmp = composition_table[glyph->u.cmp.id];
30119
30120 if (cmp->rbearing > cmp->pixel_width)
30121 *right = cmp->rbearing - cmp->pixel_width;
30122 if (cmp->lbearing < 0)
30123 *left = - cmp->lbearing;
30124 }
30125 else
30126 {
30127 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
30128 struct font_metrics metrics;
30129
30130 composition_gstring_width (gstring, glyph->slice.cmp.from,
30131 glyph->slice.cmp.to + 1, &metrics);
30132 if (metrics.rbearing > metrics.width)
30133 *right = metrics.rbearing - metrics.width;
30134 if (metrics.lbearing < 0)
30135 *left = - metrics.lbearing;
30136 }
30137 }
30138 }
30139
30140
30141
30142
30143
30144
30145 static int
30146 left_overwritten (struct glyph_string *s)
30147 {
30148 int k;
30149
30150 if (s->left_overhang)
30151 {
30152 int x = 0, i;
30153 struct glyph *glyphs = s->row->glyphs[s->area];
30154 int first = s->first_glyph - glyphs;
30155
30156 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
30157 x -= glyphs[i].pixel_width;
30158
30159 k = i + 1;
30160 }
30161 else
30162 k = -1;
30163
30164 return k;
30165 }
30166
30167
30168
30169
30170
30171
30172 static int
30173 left_overwriting (struct glyph_string *s)
30174 {
30175 int i, k, x;
30176 struct glyph *glyphs = s->row->glyphs[s->area];
30177 int first = s->first_glyph - glyphs;
30178
30179 k = -1;
30180 x = 0;
30181 for (i = first - 1; i >= 0; --i)
30182 {
30183 int left, right;
30184 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30185 if (x + right > 0)
30186 k = i;
30187 x -= glyphs[i].pixel_width;
30188 }
30189
30190 return k;
30191 }
30192
30193
30194
30195
30196
30197
30198 static int
30199 right_overwritten (struct glyph_string *s)
30200 {
30201 int k = -1;
30202
30203 if (s->right_overhang)
30204 {
30205 int x = 0, i;
30206 struct glyph *glyphs = s->row->glyphs[s->area];
30207 int first = (s->first_glyph - glyphs
30208 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30209 int end = s->row->used[s->area];
30210
30211 for (i = first; i < end && s->right_overhang > x; ++i)
30212 x += glyphs[i].pixel_width;
30213
30214 k = i;
30215 }
30216
30217 return k;
30218 }
30219
30220
30221
30222
30223
30224
30225 static int
30226 right_overwriting (struct glyph_string *s)
30227 {
30228 int i, k, x;
30229 int end = s->row->used[s->area];
30230 struct glyph *glyphs = s->row->glyphs[s->area];
30231 int first = (s->first_glyph - glyphs
30232 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
30233
30234 k = -1;
30235 x = 0;
30236 for (i = first; i < end; ++i)
30237 {
30238 int left, right;
30239 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
30240 if (x - left < 0)
30241 k = i;
30242 x += glyphs[i].pixel_width;
30243 }
30244
30245 return k;
30246 }
30247
30248
30249
30250
30251
30252
30253
30254
30255
30256
30257
30258 static void
30259 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30260 {
30261
30262
30263
30264 if (start == s->row->used[s->area]
30265 && ((s->row->fill_line_p
30266 && (s->hl == DRAW_NORMAL_TEXT
30267 || s->hl == DRAW_IMAGE_RAISED
30268 || s->hl == DRAW_IMAGE_SUNKEN))
30269 || s->hl == DRAW_MOUSE_FACE))
30270 s->extends_to_end_of_line_p = true;
30271
30272
30273
30274
30275 if (s->extends_to_end_of_line_p)
30276 s->background_width = last_x - s->x + 1;
30277 else
30278 {
30279 s->background_width = s->width;
30280 #ifdef HAVE_WINDOW_SYSTEM
30281 if (FRAME_WINDOW_P (s->f)
30282 && s->hl == DRAW_CURSOR
30283 && MATRIX_ROW (s->w->current_matrix,
30284 s->w->phys_cursor.vpos)->mouse_face_p
30285 && cursor_in_mouse_face_p (s->w))
30286 {
30287
30288
30289
30290
30291 struct glyph *g = s->first_glyph;
30292 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30293 s->background_width +=
30294 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30295 regular_face, s->face);
30296
30297 s->width = s->background_width;
30298 }
30299 #endif
30300 }
30301 }
30302
30303
30304
30305
30306
30307 static struct glyph_string *
30308 glyph_string_containing_background_width (struct glyph_string *s)
30309 {
30310 if (s->cmp)
30311 while (s->cmp_from)
30312 s = s->prev;
30313
30314 return s;
30315 }
30316
30317
30318
30319
30320
30321
30322 static void
30323 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30324 {
30325 if (backward_p)
30326 {
30327 while (s)
30328 {
30329 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30330 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30331 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30332 x -= s->width;
30333 s->x = x;
30334 s = s->prev;
30335 }
30336 }
30337 else
30338 {
30339 while (s)
30340 {
30341 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30342 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30343 s->x = x;
30344 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30345 x += s->width;
30346 s = s->next;
30347 }
30348 }
30349 }
30350
30351
30352
30353
30354
30355
30356
30357
30358
30359 #ifdef HAVE_NTGUI
30360
30361
30362 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30363 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30364 #else
30365 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30366 init_glyph_string (s, char2b, w, row, area, start, hl)
30367 #endif
30368
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378
30379 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30380 do \
30381 { \
30382 s = alloca (sizeof *s); \
30383 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30384 START = fill_stretch_glyph_string (s, START, END); \
30385 append_glyph_string (&HEAD, &TAIL, s); \
30386 s->x = (X); \
30387 } \
30388 while (false)
30389
30390
30391
30392
30393
30394
30395
30396
30397
30398
30399 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30400 do \
30401 { \
30402 s = alloca (sizeof *s); \
30403 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30404 fill_image_glyph_string (s); \
30405 append_glyph_string (&HEAD, &TAIL, s); \
30406 ++START; \
30407 s->x = (X); \
30408 } \
30409 while (false)
30410
30411 #ifndef HAVE_XWIDGETS
30412 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30413 eassume (false)
30414 #else
30415 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30416 do \
30417 { \
30418 s = alloca (sizeof *s); \
30419 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30420 fill_xwidget_glyph_string (s); \
30421 append_glyph_string (&(HEAD), &(TAIL), s); \
30422 ++(START); \
30423 s->x = (X); \
30424 } \
30425 while (false)
30426 #endif
30427
30428
30429
30430
30431
30432
30433
30434
30435
30436
30437 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30438 do \
30439 { \
30440 int face_id; \
30441 unsigned *char2b; \
30442 \
30443 face_id = (row)->glyphs[area][START].face_id; \
30444 \
30445 s = alloca (sizeof *s); \
30446 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30447 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30448 append_glyph_string (&HEAD, &TAIL, s); \
30449 s->x = (X); \
30450 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30451 } \
30452 while (false)
30453
30454
30455
30456
30457
30458
30459
30460
30461
30462
30463
30464 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30465 do { \
30466 int face_id = (row)->glyphs[area][START].face_id; \
30467 struct face *base_face = FACE_FROM_ID (f, face_id); \
30468 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30469 struct composition *cmp = composition_table[cmp_id]; \
30470 unsigned *char2b; \
30471 struct glyph_string *first_s = NULL; \
30472 int n; \
30473 \
30474 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30475 \
30476
30477 \
30478 for (n = 0; n < cmp->glyph_len;) \
30479 { \
30480 s = alloca (sizeof *s); \
30481 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30482 append_glyph_string (&(HEAD), &(TAIL), s); \
30483 s->cmp = cmp; \
30484 s->cmp_from = n; \
30485 s->x = (X); \
30486 if (n == 0) \
30487 first_s = s; \
30488 n = fill_composite_glyph_string (s, base_face, overlaps); \
30489 } \
30490 \
30491 ++START; \
30492 s = first_s; \
30493 } while (false)
30494
30495
30496
30497
30498
30499 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30500 do { \
30501 int face_id; \
30502 unsigned *char2b; \
30503 Lisp_Object gstring; \
30504 \
30505 face_id = (row)->glyphs[area][START].face_id; \
30506 gstring = (composition_gstring_from_id \
30507 ((row)->glyphs[area][START].u.cmp.id)); \
30508 s = alloca (sizeof *s); \
30509 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30510 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30511 append_glyph_string (&(HEAD), &(TAIL), s); \
30512 s->x = (X); \
30513 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30514 } while (false)
30515
30516
30517
30518
30519
30520
30521 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30522 do \
30523 { \
30524 int face_id; \
30525 \
30526 face_id = (row)->glyphs[area][START].face_id; \
30527 \
30528 s = alloca (sizeof *s); \
30529 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30530 append_glyph_string (&HEAD, &TAIL, s); \
30531 s->x = (X); \
30532 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30533 overlaps); \
30534 } \
30535 while (false)
30536
30537
30538
30539
30540
30541
30542
30543
30544
30545
30546
30547
30548 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30549 do \
30550 { \
30551 HEAD = TAIL = NULL; \
30552 while (START < END) \
30553 { \
30554 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30555 switch (first_glyph->type) \
30556 { \
30557 case CHAR_GLYPH: \
30558 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30559 HL, X, LAST_X); \
30560 break; \
30561 \
30562 case COMPOSITE_GLYPH: \
30563 if (first_glyph->u.cmp.automatic) \
30564 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30565 HL, X, LAST_X); \
30566 else \
30567 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30568 HL, X, LAST_X); \
30569 break; \
30570 \
30571 case STRETCH_GLYPH: \
30572 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30573 HL, X, LAST_X); \
30574 break; \
30575 \
30576 case IMAGE_GLYPH: \
30577 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30578 HL, X, LAST_X); \
30579 break;
30580
30581 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30582 case XWIDGET_GLYPH: \
30583 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30584 HL, X, LAST_X); \
30585 break;
30586
30587 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30588 case GLYPHLESS_GLYPH: \
30589 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30590 HL, X, LAST_X); \
30591 break; \
30592 \
30593 default: \
30594 emacs_abort (); \
30595 } \
30596 \
30597 if (s) \
30598 { \
30599 set_glyph_string_background_width (s, START, LAST_X); \
30600 (X) += s->width; \
30601 } \
30602 } \
30603 } while (false)
30604
30605
30606 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30607 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30608 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30609 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30610
30611
30612
30613
30614
30615
30616
30617
30618
30619
30620
30621
30622
30623
30624
30625
30626
30627
30628
30629
30630
30631
30632
30633
30634 static int
30635 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30636 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30637 enum draw_glyphs_face hl, int overlaps)
30638 {
30639 struct glyph_string *head, *tail;
30640 struct glyph_string *s;
30641 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30642 int i, j, x_reached, last_x, area_left = 0;
30643 struct frame *f = XFRAME (WINDOW_FRAME (w));
30644
30645 ALLOCATE_HDC (hdc, f);
30646
30647
30648 end = min (end, row->used[area]);
30649 start = clip_to_bounds (0, start, end);
30650
30651
30652
30653 if (row->full_width_p)
30654 {
30655
30656
30657 area_left = WINDOW_LEFT_EDGE_X (w);
30658 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30659 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30660 }
30661 else
30662 {
30663 area_left = window_box_left (w, area);
30664 last_x = area_left + window_box_width (w, area);
30665 }
30666 x += area_left;
30667
30668
30669
30670
30671
30672 i = start;
30673 USE_SAFE_ALLOCA;
30674 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30675 if (tail)
30676 {
30677 s = glyph_string_containing_background_width (tail);
30678 x_reached = s->x + s->background_width;
30679 }
30680 else
30681 x_reached = x;
30682
30683
30684
30685
30686 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30687 {
30688 struct glyph_string *h, *t;
30689 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30690 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30691 bool check_mouse_face = false;
30692 int dummy_x = 0;
30693
30694
30695
30696 if (area == TEXT_AREA && row->mouse_face_p
30697 && hlinfo->mouse_face_beg_row >= 0
30698 && hlinfo->mouse_face_end_row >= 0)
30699 {
30700 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30701
30702 if (row_vpos >= hlinfo->mouse_face_beg_row
30703 && row_vpos <= hlinfo->mouse_face_end_row)
30704 {
30705 check_mouse_face = true;
30706 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30707 ? hlinfo->mouse_face_beg_col : 0;
30708 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30709 ? hlinfo->mouse_face_end_col
30710 : row->used[TEXT_AREA];
30711 }
30712 }
30713
30714
30715 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30716 for (s = head; s; s = s->next)
30717 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30718
30719
30720
30721
30722
30723
30724 i = left_overwritten (head);
30725 if (i >= 0)
30726 {
30727 enum draw_glyphs_face overlap_hl;
30728
30729
30730
30731
30732
30733
30734
30735
30736 if (check_mouse_face
30737 && mouse_beg_col < start && mouse_end_col > i)
30738 overlap_hl = DRAW_MOUSE_FACE;
30739 else
30740 overlap_hl = DRAW_NORMAL_TEXT;
30741
30742 if (hl != overlap_hl)
30743 clip_head = head;
30744 j = i;
30745 BUILD_GLYPH_STRINGS (j, start, h, t,
30746 overlap_hl, dummy_x, last_x);
30747 start = i;
30748 compute_overhangs_and_x (t, head->x, true);
30749 prepend_glyph_string_lists (&head, &tail, h, t);
30750 if (clip_head == NULL)
30751 clip_head = head;
30752 }
30753
30754
30755
30756
30757
30758
30759
30760
30761 i = left_overwriting (head);
30762 if (i >= 0)
30763 {
30764 enum draw_glyphs_face overlap_hl;
30765
30766 if (check_mouse_face
30767 && mouse_beg_col < start && mouse_end_col > i)
30768 overlap_hl = DRAW_MOUSE_FACE;
30769 else
30770 overlap_hl = DRAW_NORMAL_TEXT;
30771
30772 if (hl == overlap_hl || clip_head == NULL)
30773 clip_head = head;
30774 BUILD_GLYPH_STRINGS (i, start, h, t,
30775 overlap_hl, dummy_x, last_x);
30776 for (s = h; s; s = s->next)
30777 s->background_filled_p = true;
30778 compute_overhangs_and_x (t, head->x, true);
30779 prepend_glyph_string_lists (&head, &tail, h, t);
30780 }
30781
30782
30783
30784
30785
30786 i = right_overwritten (tail);
30787 if (i >= 0)
30788 {
30789 enum draw_glyphs_face overlap_hl;
30790
30791 if (check_mouse_face
30792 && mouse_beg_col < i && mouse_end_col > end)
30793 overlap_hl = DRAW_MOUSE_FACE;
30794 else
30795 overlap_hl = DRAW_NORMAL_TEXT;
30796
30797 if (hl != overlap_hl)
30798 clip_tail = tail;
30799 BUILD_GLYPH_STRINGS (end, i, h, t,
30800 overlap_hl, x, last_x);
30801
30802
30803 compute_overhangs_and_x (h, tail->x + tail->width, false);
30804 append_glyph_string_lists (&head, &tail, h, t);
30805 if (clip_tail == NULL)
30806 clip_tail = tail;
30807 }
30808
30809
30810
30811
30812
30813
30814 i = right_overwriting (tail);
30815 if (i >= 0)
30816 {
30817 enum draw_glyphs_face overlap_hl;
30818 if (check_mouse_face
30819 && mouse_beg_col < i && mouse_end_col > end)
30820 overlap_hl = DRAW_MOUSE_FACE;
30821 else
30822 overlap_hl = DRAW_NORMAL_TEXT;
30823
30824 if (hl == overlap_hl || clip_tail == NULL)
30825 clip_tail = tail;
30826 i++;
30827 BUILD_GLYPH_STRINGS (end, i, h, t,
30828 overlap_hl, x, last_x);
30829 for (s = h; s; s = s->next)
30830 s->background_filled_p = true;
30831 compute_overhangs_and_x (h, tail->x + tail->width, false);
30832 append_glyph_string_lists (&head, &tail, h, t);
30833 }
30834 tail = glyph_string_containing_background_width (tail);
30835 if (clip_tail)
30836 clip_tail = glyph_string_containing_background_width (clip_tail);
30837 if (clip_head || clip_tail)
30838 for (s = head; s; s = s->next)
30839 {
30840 s->clip_head = clip_head;
30841 s->clip_tail = clip_tail;
30842 }
30843 }
30844
30845
30846 for (s = head; s; s = s->next)
30847 FRAME_RIF (f)->draw_glyph_string (s);
30848
30849
30850
30851 if (area == TEXT_AREA
30852 && !row->full_width_p
30853
30854
30855
30856 && !overlaps)
30857 {
30858 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30859 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30860 : (tail ? tail->x + tail->background_width : x));
30861 x0 -= area_left;
30862 x1 -= area_left;
30863
30864 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30865 row->y, MATRIX_ROW_BOTTOM_Y (row));
30866 }
30867
30868
30869
30870 if (row->full_width_p)
30871 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30872 else
30873 x_reached -= area_left;
30874
30875 RELEASE_HDC (hdc, f);
30876
30877 SAFE_FREE ();
30878 return x_reached;
30879 }
30880
30881
30882
30883
30884
30885
30886
30887
30888 struct font *
30889 font_for_underline_metrics (struct glyph_string *s)
30890 {
30891 struct glyph *g0 = s->row->glyphs[s->area], *g;
30892
30893 for (g = s->first_glyph - 1; g >= g0; g--)
30894 {
30895 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30896 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30897 break;
30898 }
30899
30900
30901 if (g == s->first_glyph - 1)
30902 return s->font;
30903 else
30904 {
30905
30906
30907 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30908 }
30909 }
30910
30911
30912
30913
30914 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30915 { \
30916 if (!it->f->fonts_changed \
30917 && (it->glyph_row->glyphs[area] \
30918 < it->glyph_row->glyphs[area + 1])) \
30919 { \
30920 it->w->ncols_scale_factor++; \
30921 it->f->fonts_changed = true; \
30922 } \
30923 }
30924
30925
30926
30927
30928 static void
30929 append_glyph (struct it *it)
30930 {
30931 struct glyph *glyph;
30932 enum glyph_row_area area = it->area;
30933
30934 eassert (it->glyph_row);
30935 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30936
30937 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30938 if (glyph < it->glyph_row->glyphs[area + 1])
30939 {
30940
30941
30942 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30943 {
30944 struct glyph *g;
30945
30946
30947 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30948 g[1] = *g;
30949 glyph = it->glyph_row->glyphs[area];
30950 }
30951 glyph->charpos = CHARPOS (it->position);
30952 glyph->object = it->object;
30953 if (it->pixel_width > 0)
30954 {
30955 eassert (it->pixel_width <= SHRT_MAX);
30956 glyph->pixel_width = it->pixel_width;
30957 glyph->padding_p = false;
30958 }
30959 else
30960 {
30961
30962
30963 glyph->pixel_width = 1;
30964 glyph->padding_p = true;
30965 }
30966 glyph->ascent = it->ascent;
30967 glyph->descent = it->descent;
30968 glyph->voffset = it->voffset;
30969 glyph->type = CHAR_GLYPH;
30970 glyph->avoid_cursor_p = it->avoid_cursor_p;
30971 glyph->multibyte_p = it->multibyte_p;
30972 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30973 {
30974
30975
30976 glyph->right_box_line_p = it->start_of_box_run_p;
30977 glyph->left_box_line_p = it->end_of_box_run_p;
30978 }
30979 else
30980 {
30981 glyph->left_box_line_p = it->start_of_box_run_p;
30982 glyph->right_box_line_p = it->end_of_box_run_p;
30983 }
30984 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30985 || it->phys_descent > it->descent);
30986 glyph->glyph_not_available_p = it->glyph_not_available_p;
30987 glyph->face_id = it->face_id;
30988 glyph->u.ch = it->char_to_display;
30989 glyph->slice.img = null_glyph_slice;
30990 glyph->font_type = FONT_TYPE_UNKNOWN;
30991 if (it->bidi_p)
30992 {
30993 glyph->resolved_level = it->bidi_it.resolved_level;
30994 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30995 glyph->bidi_type = it->bidi_it.type;
30996 }
30997 else
30998 {
30999 glyph->resolved_level = 0;
31000 glyph->bidi_type = UNKNOWN_BT;
31001 }
31002 ++it->glyph_row->used[area];
31003 }
31004 else
31005 IT_EXPAND_MATRIX_WIDTH (it, area);
31006 }
31007
31008
31009
31010
31011 static void
31012 append_composite_glyph (struct it *it)
31013 {
31014 struct glyph *glyph;
31015 enum glyph_row_area area = it->area;
31016
31017 eassert (it->glyph_row);
31018
31019 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31020 if (glyph < it->glyph_row->glyphs[area + 1])
31021 {
31022
31023
31024 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
31025 {
31026 struct glyph *g;
31027
31028
31029 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31030 g[1] = *g;
31031 glyph = it->glyph_row->glyphs[it->area];
31032 }
31033 glyph->charpos = it->cmp_it.charpos;
31034 glyph->object = it->object;
31035 eassert (it->pixel_width <= SHRT_MAX);
31036 glyph->pixel_width = it->pixel_width;
31037 glyph->ascent = it->ascent;
31038 glyph->descent = it->descent;
31039 glyph->voffset = it->voffset;
31040 glyph->type = COMPOSITE_GLYPH;
31041 if (it->cmp_it.ch < 0)
31042 {
31043 glyph->u.cmp.automatic = false;
31044 glyph->u.cmp.id = it->cmp_it.id;
31045 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
31046 }
31047 else
31048 {
31049 glyph->u.cmp.automatic = true;
31050 glyph->u.cmp.id = it->cmp_it.id;
31051 glyph->slice.cmp.from = it->cmp_it.from;
31052 glyph->slice.cmp.to = it->cmp_it.to - 1;
31053 }
31054 glyph->avoid_cursor_p = it->avoid_cursor_p;
31055 glyph->multibyte_p = it->multibyte_p;
31056 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31057 {
31058
31059
31060 glyph->right_box_line_p = it->start_of_box_run_p;
31061 glyph->left_box_line_p = it->end_of_box_run_p;
31062 }
31063 else
31064 {
31065 glyph->left_box_line_p = it->start_of_box_run_p;
31066 glyph->right_box_line_p = it->end_of_box_run_p;
31067 }
31068 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31069 || it->phys_descent > it->descent);
31070 glyph->padding_p = false;
31071 glyph->glyph_not_available_p = it->glyph_not_available_p;
31072 glyph->face_id = it->face_id;
31073 glyph->font_type = FONT_TYPE_UNKNOWN;
31074 if (it->bidi_p)
31075 {
31076 glyph->resolved_level = it->bidi_it.resolved_level;
31077 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31078 glyph->bidi_type = it->bidi_it.type;
31079 }
31080 ++it->glyph_row->used[area];
31081 }
31082 else
31083 IT_EXPAND_MATRIX_WIDTH (it, area);
31084 }
31085
31086
31087
31088
31089
31090 static void
31091 take_vertical_position_into_account (struct it *it)
31092 {
31093 if (it->voffset)
31094 {
31095 if (it->voffset < 0)
31096
31097
31098 it->ascent -= it->voffset;
31099 else
31100
31101
31102 it->descent += it->voffset;
31103 }
31104 }
31105
31106
31107
31108
31109
31110
31111 static void
31112 produce_image_glyph (struct it *it)
31113 {
31114 struct image *img;
31115 struct face *face;
31116 int glyph_ascent, crop;
31117 struct glyph_slice slice;
31118
31119 eassert (it->what == IT_IMAGE);
31120
31121 face = FACE_FROM_ID (it->f, it->face_id);
31122
31123 prepare_face_for_display (it->f, face);
31124
31125 if (it->image_id < 0)
31126 {
31127
31128 it->ascent = it->phys_ascent = 0;
31129 it->descent = it->phys_descent = 0;
31130 it->pixel_width = 0;
31131 it->nglyphs = 0;
31132 return;
31133 }
31134
31135 img = IMAGE_FROM_ID (it->f, it->image_id);
31136
31137 prepare_image_for_display (it->f, img);
31138
31139 slice.x = slice.y = 0;
31140 slice.width = img->width;
31141 slice.height = img->height;
31142
31143 if (FIXNUMP (it->slice.x))
31144 slice.x = XFIXNUM (it->slice.x);
31145 else if (FLOATP (it->slice.x))
31146 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
31147
31148 if (FIXNUMP (it->slice.y))
31149 slice.y = XFIXNUM (it->slice.y);
31150 else if (FLOATP (it->slice.y))
31151 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
31152
31153 if (FIXNUMP (it->slice.width))
31154 slice.width = XFIXNUM (it->slice.width);
31155 else if (FLOATP (it->slice.width))
31156 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
31157
31158 if (FIXNUMP (it->slice.height))
31159 slice.height = XFIXNUM (it->slice.height);
31160 else if (FLOATP (it->slice.height))
31161 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
31162
31163 if (slice.x >= img->width)
31164 slice.x = img->width;
31165 if (slice.y >= img->height)
31166 slice.y = img->height;
31167 if (slice.x + slice.width >= img->width)
31168 slice.width = img->width - slice.x;
31169 if (slice.y + slice.height > img->height)
31170 slice.height = img->height - slice.y;
31171
31172 if (slice.width == 0 || slice.height == 0)
31173 return;
31174
31175 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
31176
31177 it->descent = slice.height - glyph_ascent;
31178 if (slice.y == 0)
31179 it->descent += img->vmargin;
31180 if (slice.y + slice.height == img->height)
31181 it->descent += img->vmargin;
31182 it->phys_descent = it->descent;
31183
31184 it->pixel_width = slice.width;
31185 if (slice.x == 0)
31186 it->pixel_width += img->hmargin;
31187 if (slice.x + slice.width == img->width)
31188 it->pixel_width += img->hmargin;
31189
31190
31191
31192 if (it->descent < 0)
31193 it->descent = 0;
31194
31195 it->nglyphs = 1;
31196
31197 if (face->box != FACE_NO_BOX)
31198 {
31199
31200
31201 if (face->box_horizontal_line_width > 0)
31202 {
31203 if (slice.y == 0)
31204 it->ascent += face->box_horizontal_line_width;
31205 if (slice.y + slice.height == img->height)
31206 it->descent += face->box_horizontal_line_width;
31207 }
31208
31209 if (face->box_vertical_line_width > 0)
31210 {
31211 if (it->start_of_box_run_p && slice.x == 0)
31212 it->pixel_width += face->box_vertical_line_width;
31213 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
31214 it->pixel_width += face->box_vertical_line_width;
31215 }
31216 }
31217
31218 take_vertical_position_into_account (it);
31219
31220
31221
31222 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
31223 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31224 {
31225 it->pixel_width -= crop;
31226 slice.width -= crop;
31227 }
31228
31229 if (it->glyph_row)
31230 {
31231 struct glyph *glyph;
31232 enum glyph_row_area area = it->area;
31233
31234 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31235 if (it->glyph_row->reversed_p)
31236 {
31237 struct glyph *g;
31238
31239
31240 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31241 g[1] = *g;
31242 glyph = it->glyph_row->glyphs[it->area];
31243 }
31244 if (glyph < it->glyph_row->glyphs[area + 1])
31245 {
31246 glyph->charpos = CHARPOS (it->position);
31247 glyph->object = it->object;
31248 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31249 glyph->ascent = glyph_ascent;
31250 glyph->descent = it->descent;
31251 glyph->voffset = it->voffset;
31252 glyph->type = IMAGE_GLYPH;
31253 glyph->avoid_cursor_p = it->avoid_cursor_p;
31254 glyph->multibyte_p = it->multibyte_p;
31255 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31256 {
31257
31258
31259 glyph->right_box_line_p = it->start_of_box_run_p;
31260 glyph->left_box_line_p = it->end_of_box_run_p;
31261 }
31262 else
31263 {
31264 glyph->left_box_line_p = it->start_of_box_run_p;
31265 glyph->right_box_line_p = it->end_of_box_run_p;
31266 }
31267 glyph->overlaps_vertically_p = false;
31268 glyph->padding_p = false;
31269 glyph->glyph_not_available_p = false;
31270 glyph->face_id = it->face_id;
31271 glyph->u.img_id = img->id;
31272 glyph->slice.img = slice;
31273 glyph->font_type = FONT_TYPE_UNKNOWN;
31274 if (it->bidi_p)
31275 {
31276 glyph->resolved_level = it->bidi_it.resolved_level;
31277 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31278 glyph->bidi_type = it->bidi_it.type;
31279 }
31280 ++it->glyph_row->used[area];
31281 }
31282 else
31283 IT_EXPAND_MATRIX_WIDTH (it, area);
31284 }
31285 }
31286
31287 static void
31288 produce_xwidget_glyph (struct it *it)
31289 {
31290 #ifdef HAVE_XWIDGETS
31291 struct xwidget *xw;
31292 int glyph_ascent, crop;
31293 eassert (it->what == IT_XWIDGET);
31294
31295 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31296
31297 prepare_face_for_display (it->f, face);
31298
31299 xw = it->xwidget;
31300 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31301 it->descent = xw->height/2;
31302 it->phys_descent = it->descent;
31303 it->pixel_width = xw->width;
31304
31305
31306 if (it->descent < 0)
31307 it->descent = 0;
31308
31309 it->nglyphs = 1;
31310
31311 if (face->box != FACE_NO_BOX)
31312 {
31313 if (face->box_horizontal_line_width > 0)
31314 {
31315 it->ascent += face->box_horizontal_line_width;
31316 it->descent += face->box_horizontal_line_width;
31317 }
31318
31319 if (face->box_vertical_line_width > 0)
31320 {
31321 if (it->start_of_box_run_p)
31322 it->pixel_width += face->box_vertical_line_width;
31323 it->pixel_width += face->box_vertical_line_width;
31324 }
31325 }
31326
31327 take_vertical_position_into_account (it);
31328
31329
31330
31331 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31332 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31333 it->pixel_width -= crop;
31334
31335 if (it->glyph_row)
31336 {
31337 enum glyph_row_area area = it->area;
31338 struct glyph *glyph
31339 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31340
31341 if (it->glyph_row->reversed_p)
31342 {
31343 struct glyph *g;
31344
31345
31346 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31347 g[1] = *g;
31348 glyph = it->glyph_row->glyphs[it->area];
31349 }
31350 if (glyph < it->glyph_row->glyphs[area + 1])
31351 {
31352 glyph->charpos = CHARPOS (it->position);
31353 glyph->object = it->object;
31354 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31355 glyph->ascent = glyph_ascent;
31356 glyph->descent = it->descent;
31357 glyph->voffset = it->voffset;
31358 glyph->type = XWIDGET_GLYPH;
31359 glyph->avoid_cursor_p = it->avoid_cursor_p;
31360 glyph->multibyte_p = it->multibyte_p;
31361 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31362 {
31363
31364
31365 glyph->right_box_line_p = it->start_of_box_run_p;
31366 glyph->left_box_line_p = it->end_of_box_run_p;
31367 }
31368 else
31369 {
31370 glyph->left_box_line_p = it->start_of_box_run_p;
31371 glyph->right_box_line_p = it->end_of_box_run_p;
31372 }
31373 glyph->overlaps_vertically_p = 0;
31374 glyph->padding_p = 0;
31375 glyph->glyph_not_available_p = 0;
31376 glyph->face_id = it->face_id;
31377 glyph->u.xwidget = it->xwidget->xwidget_id;
31378 glyph->font_type = FONT_TYPE_UNKNOWN;
31379 if (it->bidi_p)
31380 {
31381 glyph->resolved_level = it->bidi_it.resolved_level;
31382 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31383 glyph->bidi_type = it->bidi_it.type;
31384 }
31385 ++it->glyph_row->used[area];
31386 }
31387 else
31388 IT_EXPAND_MATRIX_WIDTH (it, area);
31389 }
31390 #endif
31391 }
31392
31393
31394
31395
31396
31397 static void
31398 append_stretch_glyph (struct it *it, Lisp_Object object,
31399 int width, int height, int ascent)
31400 {
31401 struct glyph *glyph;
31402 enum glyph_row_area area = it->area;
31403
31404 eassert (ascent >= 0 && ascent <= height);
31405
31406 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31407 if (glyph < it->glyph_row->glyphs[area + 1])
31408 {
31409
31410
31411 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31412 {
31413 struct glyph *g;
31414
31415
31416 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31417 g[1] = *g;
31418 glyph = it->glyph_row->glyphs[area];
31419
31420
31421
31422
31423
31424
31425
31426
31427
31428
31429
31430
31431
31432
31433
31434 if (it->current_x < it->first_visible_x)
31435 width -= it->first_visible_x - it->current_x;
31436 eassert (width > 0);
31437 }
31438 glyph->charpos = CHARPOS (it->position);
31439 glyph->object = object;
31440
31441
31442 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31443 glyph->ascent = ascent;
31444 glyph->descent = height - ascent;
31445 glyph->voffset = it->voffset;
31446 glyph->type = STRETCH_GLYPH;
31447 glyph->avoid_cursor_p = it->avoid_cursor_p;
31448 glyph->multibyte_p = it->multibyte_p;
31449 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31450 {
31451
31452
31453 glyph->right_box_line_p = it->start_of_box_run_p;
31454 glyph->left_box_line_p = it->end_of_box_run_p;
31455 }
31456 else
31457 {
31458 glyph->left_box_line_p = it->start_of_box_run_p;
31459 glyph->right_box_line_p = it->end_of_box_run_p;
31460 }
31461 glyph->overlaps_vertically_p = false;
31462 glyph->padding_p = false;
31463 glyph->glyph_not_available_p = false;
31464 glyph->face_id = it->face_id;
31465 glyph->u.stretch.ascent = ascent;
31466 glyph->u.stretch.height = height;
31467 glyph->slice.img = null_glyph_slice;
31468 glyph->font_type = FONT_TYPE_UNKNOWN;
31469 if (it->bidi_p)
31470 {
31471 glyph->resolved_level = it->bidi_it.resolved_level;
31472 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31473 glyph->bidi_type = it->bidi_it.type;
31474 }
31475 else
31476 {
31477 glyph->resolved_level = 0;
31478 glyph->bidi_type = UNKNOWN_BT;
31479 }
31480 ++it->glyph_row->used[area];
31481 }
31482 else
31483 IT_EXPAND_MATRIX_WIDTH (it, area);
31484 }
31485
31486 #endif
31487
31488
31489
31490
31491
31492
31493
31494
31495
31496
31497
31498
31499
31500
31501
31502
31503
31504
31505
31506
31507
31508
31509
31510
31511
31512
31513
31514
31515
31516
31517
31518
31519 void
31520 produce_stretch_glyph (struct it *it)
31521 {
31522
31523 Lisp_Object prop, plist;
31524 int width = 0, height = 0, align_to = -1;
31525 bool zero_width_ok_p = false;
31526 double tem;
31527 struct font *font = NULL;
31528
31529 #ifdef HAVE_WINDOW_SYSTEM
31530 int ascent = 0;
31531 bool zero_height_ok_p = false;
31532 struct face *face = NULL;
31533
31534 if (FRAME_WINDOW_P (it->f))
31535 {
31536 face = FACE_FROM_ID (it->f, it->face_id);
31537 font = face->font ? face->font : FRAME_FONT (it->f);
31538 prepare_face_for_display (it->f, face);
31539 }
31540 #endif
31541
31542
31543 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31544 plist = XCDR (it->object);
31545
31546
31547 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31548 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31549 {
31550
31551 zero_width_ok_p = true;
31552 width = (int)tem;
31553 }
31554 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31555 {
31556
31557
31558
31559 struct it it2;
31560 Lisp_Object object =
31561 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31562 unsigned char *p = (STRINGP (object)
31563 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31564 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31565 bool multibyte_p =
31566 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31567
31568 it2 = *it;
31569 if (multibyte_p)
31570 {
31571 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31572 #ifdef HAVE_WINDOW_SYSTEM
31573 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31574 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31575 IT_CHARPOS (*it),
31576 STRINGP (object)? object : Qnil);
31577 #endif
31578 }
31579 else
31580 {
31581 it2.c = it2.char_to_display = *p, it2.len = 1;
31582 if (! ASCII_CHAR_P (it2.c))
31583 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31584 }
31585
31586 it2.glyph_row = NULL;
31587 it2.what = IT_CHARACTER;
31588 PRODUCE_GLYPHS (&it2);
31589 width = NUMVAL (prop) * it2.pixel_width;
31590 }
31591 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31592 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31593 &align_to))
31594 {
31595 int x = it->current_x + it->continuation_lines_width;
31596 int x0 = x;
31597
31598 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31599 {
31600 x -= it->lnum_pixel_width;
31601
31602 if (x + it->stretch_adjust >= it->first_visible_x)
31603 x += it->stretch_adjust;
31604 }
31605
31606 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31607 align_to = (align_to < 0
31608 ? 0
31609 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31610 else if (align_to < 0)
31611 align_to = window_box_left_offset (it->w, TEXT_AREA);
31612 width = max (0, (int)tem + align_to - x);
31613
31614 int next_x = x + width;
31615 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31616 {
31617
31618
31619 if (x < it->first_visible_x)
31620 {
31621 next_x -= it->first_visible_x - x;
31622 it->stretch_adjust = it->first_visible_x - x;
31623 }
31624 else
31625 next_x -= it->stretch_adjust;
31626 }
31627 width = next_x - x0;
31628 zero_width_ok_p = true;
31629 }
31630 else
31631
31632 width = FRAME_COLUMN_WIDTH (it->f);
31633
31634 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31635 width = 1;
31636
31637 #ifdef HAVE_WINDOW_SYSTEM
31638
31639 if (FRAME_WINDOW_P (it->f))
31640 {
31641 int default_height = normal_char_height (font, ' ');
31642
31643 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31644 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31645 {
31646 height = (int)tem;
31647 zero_height_ok_p = true;
31648 }
31649 else if (prop = plist_get (plist, QCrelative_height),
31650 NUMVAL (prop) > 0)
31651 height = default_height * NUMVAL (prop);
31652 else
31653 height = default_height;
31654
31655 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31656 height = 1;
31657
31658
31659
31660
31661 if (prop = plist_get (plist, QCascent),
31662 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31663 ascent = height * NUMVAL (prop) / 100.0;
31664 else if (!NILP (prop)
31665 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31666 ascent = min (max (0, (int)tem), height);
31667 else
31668 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31669 }
31670 else
31671 #endif
31672 height = 1;
31673
31674 if (width > 0
31675 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31676 && it->current_x + width > it->last_visible_x)
31677 {
31678 width = it->last_visible_x - it->current_x;
31679 #ifdef HAVE_WINDOW_SYSTEM
31680
31681
31682 width -= FRAME_WINDOW_P (it->f);
31683 #endif
31684 }
31685
31686 if (width > 0 && height > 0 && it->glyph_row)
31687 {
31688 Lisp_Object o_object = it->object;
31689 Lisp_Object object =
31690 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31691 int n = width;
31692
31693 if (!STRINGP (object))
31694 object = it->w->contents;
31695 #ifdef HAVE_WINDOW_SYSTEM
31696 if (FRAME_WINDOW_P (it->f))
31697 append_stretch_glyph (it, object, width, height, ascent);
31698 else
31699 #endif
31700 {
31701 it->object = object;
31702 it->char_to_display = ' ';
31703 it->pixel_width = it->len = 1;
31704 while (n--)
31705 tty_append_glyph (it);
31706 it->object = o_object;
31707 }
31708 }
31709
31710 it->pixel_width = width;
31711 #ifdef HAVE_WINDOW_SYSTEM
31712 if (FRAME_WINDOW_P (it->f))
31713 {
31714 it->ascent = it->phys_ascent = ascent;
31715 it->descent = it->phys_descent = height - it->ascent;
31716 it->nglyphs = width > 0 && height > 0;
31717 take_vertical_position_into_account (it);
31718 }
31719 else
31720 #endif
31721 it->nglyphs = width;
31722 }
31723
31724
31725
31726
31727
31728
31729
31730 static void
31731 produce_special_glyphs (struct it *it, enum display_element_type what)
31732 {
31733 struct it temp_it;
31734 Lisp_Object gc;
31735 GLYPH glyph;
31736
31737 temp_it = *it;
31738 temp_it.object = Qnil;
31739 memset (&temp_it.current, 0, sizeof temp_it.current);
31740
31741 if (what == IT_CONTINUATION)
31742 {
31743
31744 if (it->bidi_it.paragraph_dir == R2L)
31745 SET_GLYPH_FROM_CHAR (glyph, '/');
31746 else
31747 SET_GLYPH_FROM_CHAR (glyph, '\\');
31748 if (it->dp
31749 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31750 {
31751
31752 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31753 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31754 }
31755 }
31756 else if (what == IT_TRUNCATION)
31757 {
31758
31759 SET_GLYPH_FROM_CHAR (glyph, '$');
31760 if (it->dp
31761 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31762 {
31763
31764 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31765 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31766 }
31767 }
31768 else
31769 emacs_abort ();
31770
31771 #ifdef HAVE_WINDOW_SYSTEM
31772
31773
31774
31775
31776
31777 if (FRAME_WINDOW_P (temp_it.f)
31778
31779
31780
31781 && temp_it.glyph_row
31782
31783
31784
31785 && temp_it.glyph_row->used[TEXT_AREA] > 0
31786 && (temp_it.glyph_row->reversed_p
31787 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31788 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31789 {
31790 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31791
31792 if (stretch_width > 0)
31793 {
31794 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31795 struct font *font =
31796 face->font ? face->font : FRAME_FONT (temp_it.f);
31797 int stretch_ascent =
31798 (((temp_it.ascent + temp_it.descent)
31799 * FONT_BASE (font)) / FONT_HEIGHT (font));
31800
31801 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31802 temp_it.ascent + temp_it.descent,
31803 stretch_ascent);
31804 }
31805 }
31806 #endif
31807
31808 temp_it.dp = NULL;
31809 temp_it.what = IT_CHARACTER;
31810 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31811 temp_it.face_id = GLYPH_FACE (glyph);
31812 temp_it.len = CHAR_BYTES (temp_it.c);
31813
31814 PRODUCE_GLYPHS (&temp_it);
31815 it->pixel_width = temp_it.pixel_width;
31816 it->nglyphs = temp_it.nglyphs;
31817 }
31818
31819
31820
31821
31822
31823
31824
31825
31826
31827 static void
31828 pad_mode_line (struct it *it, bool mode_line_p)
31829 {
31830 struct it temp_it;
31831 GLYPH glyph;
31832
31833 eassert (!FRAME_WINDOW_P (it->f));
31834 temp_it = *it;
31835 temp_it.object = Qnil;
31836 memset (&temp_it.current, 0, sizeof temp_it.current);
31837
31838 SET_GLYPH (glyph, mode_line_p ? '-' : ' ', it->base_face_id);
31839
31840 temp_it.dp = NULL;
31841 temp_it.what = IT_CHARACTER;
31842 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31843 temp_it.face_id = GLYPH_FACE (glyph);
31844 temp_it.len = CHAR_BYTES (temp_it.c);
31845
31846 PRODUCE_GLYPHS (&temp_it);
31847 it->pixel_width = temp_it.pixel_width;
31848 it->nglyphs = temp_it.nglyphs;
31849 }
31850
31851 #ifdef HAVE_WINDOW_SYSTEM
31852
31853
31854
31855
31856
31857
31858
31859
31860
31861 static Lisp_Object
31862 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31863 int boff, bool override)
31864 {
31865 Lisp_Object face_name = Qnil;
31866 int ascent, descent, height;
31867
31868 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31869 return val;
31870
31871 if (CONSP (val))
31872 {
31873 face_name = XCAR (val);
31874 val = XCDR (val);
31875 if (!NUMBERP (val))
31876 val = make_fixnum (1);
31877 if (NILP (face_name))
31878 {
31879 height = it->ascent + it->descent;
31880 goto scale;
31881 }
31882 }
31883
31884 if (NILP (face_name))
31885 {
31886 font = FRAME_FONT (it->f);
31887 boff = FRAME_BASELINE_OFFSET (it->f);
31888 }
31889 else if (EQ (face_name, Qt))
31890 {
31891 override = false;
31892 }
31893 else
31894 {
31895 int face_id;
31896 struct face *face;
31897
31898 face_id = lookup_named_face (it->w, it->f, face_name, false);
31899 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31900 if (face == NULL || ((font = face->font) == NULL))
31901 return make_fixnum (-1);
31902 boff = font->baseline_offset;
31903 if (font->vertical_centering)
31904 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31905 }
31906
31907 normal_char_ascent_descent (font, -1, &ascent, &descent);
31908
31909 if (override)
31910 {
31911 it->override_ascent = ascent;
31912 it->override_descent = descent;
31913 it->override_boff = boff;
31914 }
31915
31916 height = ascent + descent;
31917
31918 scale:
31919
31920 if (FLOATP (val))
31921 height = (int)(XFLOAT_DATA (val) * height);
31922 else if (INTEGERP (val))
31923 {
31924 intmax_t v;
31925 if (integer_to_intmax (val, &v))
31926 height *= v;
31927 }
31928
31929 return make_fixnum (height);
31930 }
31931
31932
31933
31934
31935
31936
31937
31938
31939
31940
31941
31942
31943
31944
31945 static void
31946 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31947 short upper_xoff, short upper_yoff,
31948 short lower_xoff, short lower_yoff)
31949 {
31950 struct glyph *glyph;
31951 enum glyph_row_area area = it->area;
31952
31953 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31954 if (glyph < it->glyph_row->glyphs[area + 1])
31955 {
31956
31957
31958 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31959 {
31960 struct glyph *g;
31961
31962
31963 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31964 g[1] = *g;
31965 glyph = it->glyph_row->glyphs[area];
31966 }
31967 glyph->charpos = CHARPOS (it->position);
31968 glyph->object = it->object;
31969 eassert (it->pixel_width <= SHRT_MAX);
31970 glyph->pixel_width = it->pixel_width;
31971 glyph->ascent = it->ascent;
31972 glyph->descent = it->descent;
31973 glyph->voffset = it->voffset;
31974 glyph->type = GLYPHLESS_GLYPH;
31975 glyph->u.glyphless.method = it->glyphless_method;
31976 glyph->u.glyphless.for_no_font = for_no_font;
31977 glyph->u.glyphless.len = len;
31978 glyph->u.glyphless.ch = it->c;
31979 glyph->slice.glyphless.upper_xoff = upper_xoff;
31980 glyph->slice.glyphless.upper_yoff = upper_yoff;
31981 glyph->slice.glyphless.lower_xoff = lower_xoff;
31982 glyph->slice.glyphless.lower_yoff = lower_yoff;
31983 glyph->avoid_cursor_p = it->avoid_cursor_p;
31984 glyph->multibyte_p = it->multibyte_p;
31985 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31986 {
31987
31988
31989 glyph->right_box_line_p = it->start_of_box_run_p;
31990 glyph->left_box_line_p = it->end_of_box_run_p;
31991 }
31992 else
31993 {
31994 glyph->left_box_line_p = it->start_of_box_run_p;
31995 glyph->right_box_line_p = it->end_of_box_run_p;
31996 }
31997 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31998 || it->phys_descent > it->descent);
31999 glyph->padding_p = false;
32000 glyph->glyph_not_available_p = false;
32001 glyph->face_id = face_id;
32002 glyph->font_type = FONT_TYPE_UNKNOWN;
32003 if (it->bidi_p)
32004 {
32005 glyph->resolved_level = it->bidi_it.resolved_level;
32006 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
32007 glyph->bidi_type = it->bidi_it.type;
32008 }
32009 ++it->glyph_row->used[area];
32010 }
32011 else
32012 IT_EXPAND_MATRIX_WIDTH (it, area);
32013 }
32014
32015
32016
32017
32018
32019
32020
32021
32022
32023
32024
32025 static void
32026 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
32027 {
32028 int face_id;
32029 struct face *face;
32030 struct font *font;
32031 int base_width, base_height, width, height;
32032 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
32033 int len;
32034
32035
32036
32037 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
32038 font = face->font ? face->font : FRAME_FONT (it->f);
32039 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
32040 it->ascent += font->baseline_offset;
32041 it->descent -= font->baseline_offset;
32042 base_height = it->ascent + it->descent;
32043 base_width = font->average_width;
32044
32045 face_id = merge_glyphless_glyph_face (it);
32046
32047 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
32048 {
32049 it->pixel_width = THIN_SPACE_WIDTH;
32050 len = 0;
32051 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32052 }
32053 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
32054 {
32055 width = CHARACTER_WIDTH (it->c);
32056 if (width == 0)
32057 width = 1;
32058 else if (width > 4)
32059 width = 4;
32060 it->pixel_width = base_width * width;
32061 len = 0;
32062 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
32063 }
32064 else
32065 {
32066 char buf[7];
32067 const char *str;
32068 unsigned int code[6];
32069 int upper_len;
32070 int ascent, descent;
32071 struct font_metrics metrics_upper, metrics_lower;
32072
32073 face = FACE_FROM_ID (it->f, face_id);
32074 font = face->font ? face->font : FRAME_FONT (it->f);
32075 prepare_face_for_display (it->f, face);
32076
32077 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
32078 {
32079 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
32080 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
32081 if (CONSP (acronym))
32082 acronym = XCAR (acronym);
32083 str = STRINGP (acronym) ? SSDATA (acronym) : "";
32084 }
32085 else
32086 {
32087 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
32088 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
32089 str = buf;
32090 }
32091 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
32092 code[len] = font->driver->encode_char (font, str[len]);
32093 upper_len = (len + 1) / 2;
32094 font->driver->text_extents (font, code, upper_len,
32095 &metrics_upper);
32096 font->driver->text_extents (font, code + upper_len, len - upper_len,
32097 &metrics_lower);
32098
32099
32100
32101
32102 width = max (metrics_upper.width, metrics_lower.width) + 4;
32103 upper_xoff = lower_xoff = 2;
32104 if (base_width >= width)
32105 {
32106
32107 it->pixel_width = base_width;
32108 lower_xoff = base_width - 2 - metrics_lower.width;
32109 }
32110 else
32111 {
32112
32113 it->pixel_width = width;
32114 if (metrics_upper.width >= metrics_lower.width)
32115 lower_xoff = (width - metrics_lower.width) / 2;
32116 else
32117 upper_xoff = (width - metrics_upper.width) / 2;
32118 }
32119
32120
32121
32122 height = (metrics_upper.ascent + metrics_upper.descent
32123 + metrics_lower.ascent + metrics_lower.descent) + 5;
32124
32125
32126
32127
32128
32129
32130
32131
32132 ascent = - (it->descent - (base_height + height + 1) / 2);
32133 descent = it->descent - (base_height - height) / 2;
32134 lower_yoff = descent - 2 - metrics_lower.descent;
32135 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
32136 - metrics_upper.descent);
32137
32138 if (height > base_height)
32139 {
32140 it->ascent = ascent;
32141 it->descent = descent;
32142 }
32143 }
32144
32145 it->phys_ascent = it->ascent;
32146 it->phys_descent = it->descent;
32147 if (it->glyph_row)
32148 append_glyphless_glyph (it, face_id, for_no_font, len,
32149 upper_xoff, upper_yoff,
32150 lower_xoff, lower_yoff);
32151 it->nglyphs = 1;
32152 take_vertical_position_into_account (it);
32153 }
32154
32155
32156
32157
32158
32159 #define IT_APPLY_FACE_BOX(it, face) \
32160 do { \
32161 if (face->box != FACE_NO_BOX) \
32162 { \
32163 int thick = face->box_horizontal_line_width; \
32164 if (thick > 0) \
32165 { \
32166 it->ascent += thick; \
32167 it->descent += thick; \
32168 } \
32169 \
32170 thick = face->box_vertical_line_width; \
32171 if (thick > 0) \
32172 { \
32173 if (it->start_of_box_run_p) \
32174 it->pixel_width += thick; \
32175 if (it->end_of_box_run_p) \
32176 it->pixel_width += thick; \
32177 } \
32178 } \
32179 } while (false)
32180
32181
32182
32183
32184
32185
32186 void
32187 gui_produce_glyphs (struct it *it)
32188 {
32189 int extra_line_spacing = it->extra_line_spacing;
32190
32191 it->glyph_not_available_p = false;
32192
32193 if (it->what == IT_CHARACTER)
32194 {
32195 unsigned char2b;
32196 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32197 struct font *font = face->font;
32198 struct font_metrics *pcm = NULL;
32199 int boff;
32200
32201 if (font == NULL)
32202 {
32203
32204
32205
32206 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
32207
32208 eassert (it->what == IT_GLYPHLESS);
32209 produce_glyphless_glyph (it, true,
32210 STRINGP (acronym) ? acronym : Qnil);
32211 goto done;
32212 }
32213
32214 boff = font->baseline_offset;
32215 if (font->vertical_centering)
32216 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32217
32218 if (it->char_to_display != '\n' && it->char_to_display != '\t')
32219 {
32220 it->nglyphs = 1;
32221
32222 if (it->override_ascent >= 0)
32223 {
32224 it->ascent = it->override_ascent;
32225 it->descent = it->override_descent;
32226 boff = it->override_boff;
32227 }
32228 else
32229 {
32230 it->ascent = FONT_BASE (font) + boff;
32231 it->descent = FONT_DESCENT (font) - boff;
32232 }
32233
32234 if (get_char_glyph_code (it->char_to_display, font, &char2b))
32235 {
32236 pcm = get_per_char_metric (font, &char2b);
32237 if (pcm->width == 0
32238 && pcm->rbearing == 0 && pcm->lbearing == 0)
32239 pcm = NULL;
32240 }
32241
32242 if (pcm)
32243 {
32244 it->phys_ascent = pcm->ascent + boff;
32245 it->phys_descent = pcm->descent - boff;
32246 it->pixel_width = pcm->width;
32247
32248
32249 if (it->override_ascent < 0)
32250 {
32251 if (FONT_TOO_HIGH (font))
32252 {
32253 it->ascent = it->phys_ascent;
32254 it->descent = it->phys_descent;
32255
32256
32257 if (it->ascent < 0)
32258 it->ascent = 0;
32259 if (it->descent < 0)
32260 it->descent = 0;
32261 }
32262 }
32263 }
32264 else
32265 {
32266 it->glyph_not_available_p = true;
32267 it->phys_ascent = it->ascent;
32268 it->phys_descent = it->descent;
32269 it->pixel_width = font->space_width;
32270 }
32271
32272 if (it->constrain_row_ascent_descent_p)
32273 {
32274 if (it->descent > it->max_descent)
32275 {
32276 it->ascent += it->descent - it->max_descent;
32277 it->descent = it->max_descent;
32278 }
32279 if (it->ascent > it->max_ascent)
32280 {
32281 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32282 it->ascent = it->max_ascent;
32283 }
32284 it->phys_ascent = min (it->phys_ascent, it->ascent);
32285 it->phys_descent = min (it->phys_descent, it->descent);
32286 extra_line_spacing = 0;
32287 }
32288
32289
32290
32291 bool stretched_p
32292 = it->char_to_display == ' ' && !NILP (it->space_width);
32293 if (stretched_p)
32294 it->pixel_width *= XFLOATINT (it->space_width);
32295
32296 IT_APPLY_FACE_BOX(it, face);
32297
32298
32299
32300 if (face->overline_p)
32301 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32302
32303 if (it->constrain_row_ascent_descent_p)
32304 {
32305 if (it->ascent > it->max_ascent)
32306 it->ascent = it->max_ascent;
32307 if (it->descent > it->max_descent)
32308 it->descent = it->max_descent;
32309 }
32310
32311 take_vertical_position_into_account (it);
32312
32313
32314 if (it->glyph_row)
32315 {
32316 if (stretched_p)
32317 {
32318
32319
32320 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32321 / FONT_HEIGHT (font));
32322 append_stretch_glyph (it, it->object, it->pixel_width,
32323 it->ascent + it->descent, ascent);
32324 }
32325 else
32326 append_glyph (it);
32327
32328
32329
32330
32331 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32332 it->glyph_row->contains_overlapping_glyphs_p = true;
32333 }
32334 if (! stretched_p && it->pixel_width == 0)
32335
32336
32337 it->pixel_width = 1;
32338 }
32339 else if (it->char_to_display == '\n')
32340 {
32341
32342
32343
32344
32345 Lisp_Object height;
32346 Lisp_Object total_height = Qnil;
32347
32348 it->override_ascent = -1;
32349 it->pixel_width = 0;
32350 it->nglyphs = 0;
32351
32352 height = get_it_property (it, Qline_height);
32353
32354 if (CONSP (height)
32355 && CONSP (XCDR (height))
32356 && NILP (XCDR (XCDR (height))))
32357 {
32358 total_height = XCAR (XCDR (height));
32359 height = XCAR (height);
32360 }
32361 height = calc_line_height_property (it, height, font, boff, true);
32362
32363 if (it->override_ascent >= 0)
32364 {
32365 it->ascent = it->override_ascent;
32366 it->descent = it->override_descent;
32367 boff = it->override_boff;
32368 }
32369 else
32370 {
32371 if (FONT_TOO_HIGH (font))
32372 {
32373 it->ascent = font->pixel_size + boff - 1;
32374 it->descent = -boff + 1;
32375 if (it->descent < 0)
32376 it->descent = 0;
32377 }
32378 else
32379 {
32380 it->ascent = FONT_BASE (font) + boff;
32381 it->descent = FONT_DESCENT (font) - boff;
32382 }
32383 }
32384
32385 if (EQ (height, Qt))
32386 {
32387 if (it->descent > it->max_descent)
32388 {
32389 it->ascent += it->descent - it->max_descent;
32390 it->descent = it->max_descent;
32391 }
32392 if (it->ascent > it->max_ascent)
32393 {
32394 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32395 it->ascent = it->max_ascent;
32396 }
32397 it->phys_ascent = min (it->phys_ascent, it->ascent);
32398 it->phys_descent = min (it->phys_descent, it->descent);
32399 it->constrain_row_ascent_descent_p = true;
32400 extra_line_spacing = 0;
32401 }
32402 else
32403 {
32404 Lisp_Object spacing;
32405
32406 it->phys_ascent = it->ascent;
32407 it->phys_descent = it->descent;
32408
32409 if ((it->max_ascent > 0 || it->max_descent > 0)
32410 && face->box != FACE_NO_BOX
32411 && face->box_horizontal_line_width > 0)
32412 {
32413 it->ascent += face->box_horizontal_line_width;
32414 it->descent += face->box_horizontal_line_width;
32415 }
32416 if (!NILP (height)
32417 && XFIXNUM (height) > it->ascent + it->descent)
32418 it->ascent = XFIXNUM (height) - it->descent;
32419
32420 if (!NILP (total_height))
32421 spacing = calc_line_height_property (it, total_height, font,
32422 boff, false);
32423 else
32424 {
32425 spacing = get_it_property (it, Qline_spacing);
32426 spacing = calc_line_height_property (it, spacing, font,
32427 boff, false);
32428 }
32429 if (FIXNUMP (spacing))
32430 {
32431 extra_line_spacing = XFIXNUM (spacing);
32432 if (!NILP (total_height))
32433 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32434 }
32435 }
32436 }
32437 else
32438 {
32439 if (font->space_width > 0)
32440 {
32441 int tab_width = it->tab_width * font->space_width;
32442 int x = it->current_x + it->continuation_lines_width;
32443 int x0 = x;
32444
32445 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32446 {
32447 x -= it->lnum_pixel_width;
32448
32449 if (x + it->stretch_adjust >= it->first_visible_x)
32450 x += it->stretch_adjust;
32451 }
32452
32453 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32454
32455
32456
32457
32458 if (next_tab_x - x < font->space_width)
32459 next_tab_x += tab_width;
32460 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32461 {
32462 next_tab_x += it->lnum_pixel_width;
32463
32464
32465 if (x < it->first_visible_x)
32466 {
32467 next_tab_x -= it->first_visible_x - x;
32468 it->stretch_adjust = it->first_visible_x - x;
32469 }
32470 else
32471 next_tab_x -= it->stretch_adjust;
32472 }
32473
32474 it->pixel_width = next_tab_x - x0;
32475 it->nglyphs = 1;
32476 if (FONT_TOO_HIGH (font))
32477 {
32478 if (get_char_glyph_code (' ', font, &char2b))
32479 {
32480 pcm = get_per_char_metric (font, &char2b);
32481 if (pcm->width == 0
32482 && pcm->rbearing == 0 && pcm->lbearing == 0)
32483 pcm = NULL;
32484 }
32485
32486 if (pcm)
32487 {
32488 it->ascent = pcm->ascent + boff;
32489 it->descent = pcm->descent - boff;
32490 }
32491 else
32492 {
32493 it->ascent = font->pixel_size + boff - 1;
32494 it->descent = -boff + 1;
32495 }
32496 if (it->ascent < 0)
32497 it->ascent = 0;
32498 if (it->descent < 0)
32499 it->descent = 0;
32500 }
32501 else
32502 {
32503 it->ascent = FONT_BASE (font) + boff;
32504 it->descent = FONT_DESCENT (font) - boff;
32505 }
32506 it->phys_ascent = it->ascent;
32507 it->phys_descent = it->descent;
32508
32509 if (it->glyph_row)
32510 {
32511 append_stretch_glyph (it, it->object, it->pixel_width,
32512 it->ascent + it->descent, it->ascent);
32513 }
32514 }
32515 else
32516 {
32517 it->pixel_width = 0;
32518 it->nglyphs = 1;
32519 }
32520 }
32521
32522 if (FONT_TOO_HIGH (font))
32523 {
32524 int font_ascent, font_descent;
32525
32526
32527
32528
32529
32530
32531
32532
32533 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32534 it->max_ascent = max (it->max_ascent, font_ascent);
32535 it->max_descent = max (it->max_descent, font_descent);
32536 }
32537
32538 if (it->ascent < 0)
32539 it->ascent = 0;
32540 if (it->descent < 0)
32541 it->descent = 0;
32542 }
32543 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32544 {
32545
32546
32547
32548
32549
32550
32551
32552
32553 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32554 int boff;
32555 struct composition *cmp = composition_table[it->cmp_it.id];
32556 int glyph_len = cmp->glyph_len;
32557 struct font *font = face->font;
32558
32559 it->nglyphs = 1;
32560
32561
32562
32563
32564
32565
32566
32567
32568 if (! cmp->font || cmp->font != font)
32569 {
32570
32571
32572
32573
32574 int font_ascent, font_descent, font_height;
32575
32576 int leftmost, rightmost, lowest, highest;
32577 int lbearing, rbearing;
32578 int i, width, ascent, descent;
32579 int c;
32580 unsigned char2b;
32581 struct font_metrics *pcm;
32582 ptrdiff_t pos;
32583
32584 eassume (0 < glyph_len);
32585 do
32586 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32587 while (c == '\t' && 0 < --glyph_len);
32588
32589 bool right_padded = glyph_len < cmp->glyph_len;
32590 for (i = 0; i < glyph_len; i++)
32591 {
32592 c = COMPOSITION_GLYPH (cmp, i);
32593 if (c != '\t')
32594 break;
32595 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32596 }
32597 bool left_padded = i > 0;
32598
32599 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32600 : IT_CHARPOS (*it));
32601
32602 bool font_not_found_p = font == NULL;
32603 if (font_not_found_p)
32604 {
32605 face = face->ascii_face;
32606 font = face->font;
32607 }
32608 boff = font->baseline_offset;
32609 if (font->vertical_centering)
32610 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32611 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32612 font_ascent += boff;
32613 font_descent -= boff;
32614 font_height = font_ascent + font_descent;
32615
32616 cmp->font = font;
32617
32618 pcm = NULL;
32619 if (! font_not_found_p)
32620 {
32621 get_char_face_and_encoding (it->f, c, it->face_id,
32622 &char2b, false);
32623 pcm = get_per_char_metric (font, &char2b);
32624 }
32625
32626
32627 if (pcm)
32628 {
32629 width = cmp->glyph_len > 0 ? pcm->width : 0;
32630 ascent = pcm->ascent;
32631 descent = pcm->descent;
32632 lbearing = pcm->lbearing;
32633 rbearing = pcm->rbearing;
32634 }
32635 else
32636 {
32637 width = cmp->glyph_len > 0 ? font->space_width : 0;
32638 ascent = FONT_BASE (font);
32639 descent = FONT_DESCENT (font);
32640 lbearing = 0;
32641 rbearing = width;
32642 }
32643
32644 rightmost = width;
32645 leftmost = 0;
32646 lowest = - descent + boff;
32647 highest = ascent + boff;
32648
32649 if (! font_not_found_p
32650 && font->default_ascent
32651 && CHAR_TABLE_P (Vuse_default_ascent)
32652 && !NILP (Faref (Vuse_default_ascent,
32653 make_fixnum (it->char_to_display))))
32654 highest = font->default_ascent + boff;
32655
32656
32657
32658
32659 cmp->offsets[i * 2] = 0;
32660 cmp->offsets[i * 2 + 1] = boff;
32661 cmp->lbearing = lbearing;
32662 cmp->rbearing = rbearing;
32663
32664
32665 for (i++; i < glyph_len; i++)
32666 {
32667 int left, right, btm, top;
32668 int ch = COMPOSITION_GLYPH (cmp, i);
32669 int face_id;
32670 struct face *this_face;
32671
32672 if (ch == '\t')
32673 ch = ' ';
32674 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32675 this_face = FACE_FROM_ID (it->f, face_id);
32676 font = this_face->font;
32677
32678 if (font == NULL)
32679 pcm = NULL;
32680 else
32681 {
32682 get_char_face_and_encoding (it->f, ch, face_id,
32683 &char2b, false);
32684 pcm = get_per_char_metric (font, &char2b);
32685 }
32686 if (! pcm)
32687 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32688 else
32689 {
32690 width = pcm->width;
32691 ascent = pcm->ascent;
32692 descent = pcm->descent;
32693 lbearing = pcm->lbearing;
32694 rbearing = pcm->rbearing;
32695 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32696 {
32697
32698
32699 left = (leftmost + rightmost - width) / 2;
32700 btm = - descent + boff;
32701 if (font->relative_compose
32702 && (! CHAR_TABLE_P (Vignore_relative_composition)
32703 || NILP (Faref (Vignore_relative_composition,
32704 make_fixnum (ch)))))
32705 {
32706
32707 if (- descent >= font->relative_compose)
32708
32709 btm = highest + 1;
32710 else if (ascent <= 0)
32711
32712 btm = lowest - 1 - ascent - descent;
32713 }
32714 }
32715 else
32716 {
32717
32718
32719
32720
32721
32722
32723
32724
32725
32726
32727
32728
32729
32730
32731
32732 int rule = COMPOSITION_RULE (cmp, i);
32733 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32734
32735 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32736 grefx = gref % 3, nrefx = nref % 3;
32737 grefy = gref / 3, nrefy = nref / 3;
32738 if (xoff)
32739 xoff = font_height * (xoff - 128) / 256;
32740 if (yoff)
32741 yoff = font_height * (yoff - 128) / 256;
32742
32743 left = (leftmost
32744 + grefx * (rightmost - leftmost) / 2
32745 - nrefx * width / 2
32746 + xoff);
32747
32748 btm = ((grefy == 0 ? highest
32749 : grefy == 1 ? 0
32750 : grefy == 2 ? lowest
32751 : (highest + lowest) / 2)
32752 - (nrefy == 0 ? ascent + descent
32753 : nrefy == 1 ? descent - boff
32754 : nrefy == 2 ? 0
32755 : (ascent + descent) / 2)
32756 + yoff);
32757 }
32758
32759 cmp->offsets[i * 2] = left;
32760 cmp->offsets[i * 2 + 1] = btm + descent;
32761
32762
32763 if (width > 0)
32764 {
32765 right = left + width;
32766 if (left < leftmost)
32767 leftmost = left;
32768 if (right > rightmost)
32769 rightmost = right;
32770 }
32771 top = btm + descent + ascent;
32772 if (top > highest)
32773 highest = top;
32774 if (btm < lowest)
32775 lowest = btm;
32776
32777 if (cmp->lbearing > left + lbearing)
32778 cmp->lbearing = left + lbearing;
32779 if (cmp->rbearing < left + rbearing)
32780 cmp->rbearing = left + rbearing;
32781 }
32782 }
32783
32784
32785
32786
32787 if (leftmost < 0)
32788 {
32789 for (i = 0; i < cmp->glyph_len; i++)
32790 cmp->offsets[i * 2] -= leftmost;
32791 rightmost -= leftmost;
32792 cmp->lbearing -= leftmost;
32793 cmp->rbearing -= leftmost;
32794 }
32795
32796 if (left_padded && cmp->lbearing < 0)
32797 {
32798 for (i = 0; i < cmp->glyph_len; i++)
32799 cmp->offsets[i * 2] -= cmp->lbearing;
32800 rightmost -= cmp->lbearing;
32801 cmp->rbearing -= cmp->lbearing;
32802 cmp->lbearing = 0;
32803 }
32804 if (right_padded && rightmost < cmp->rbearing)
32805 {
32806 rightmost = cmp->rbearing;
32807 }
32808
32809 cmp->pixel_width = rightmost;
32810 cmp->ascent = highest;
32811 cmp->descent = - lowest;
32812 if (cmp->ascent < font_ascent)
32813 cmp->ascent = font_ascent;
32814 if (cmp->descent < font_descent)
32815 cmp->descent = font_descent;
32816 }
32817
32818 if (it->glyph_row
32819 && (cmp->lbearing < 0
32820 || cmp->rbearing > cmp->pixel_width))
32821 it->glyph_row->contains_overlapping_glyphs_p = true;
32822
32823 it->pixel_width = cmp->pixel_width;
32824 it->ascent = it->phys_ascent = cmp->ascent;
32825 it->descent = it->phys_descent = cmp->descent;
32826 IT_APPLY_FACE_BOX(it, face);
32827
32828
32829
32830 if (face->overline_p)
32831 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32832
32833 take_vertical_position_into_account (it);
32834 if (it->ascent < 0)
32835 it->ascent = 0;
32836 if (it->descent < 0)
32837 it->descent = 0;
32838
32839 if (it->glyph_row && cmp->glyph_len > 0)
32840 append_composite_glyph (it);
32841 }
32842 else if (it->what == IT_COMPOSITION)
32843 {
32844
32845 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32846 Lisp_Object gstring;
32847 struct font_metrics metrics;
32848
32849 it->nglyphs = 1;
32850
32851 gstring = composition_gstring_from_id (it->cmp_it.id);
32852 it->pixel_width
32853 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32854 &metrics);
32855 if (it->pixel_width == 0)
32856 {
32857 it->glyph_not_available_p = true;
32858 it->phys_ascent = it->ascent;
32859 it->phys_descent = it->descent;
32860 it->pixel_width = face->font->space_width;
32861 }
32862 else
32863 {
32864 if (it->glyph_row
32865 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32866 it->glyph_row->contains_overlapping_glyphs_p = true;
32867 it->ascent = it->phys_ascent = metrics.ascent;
32868 it->descent = it->phys_descent = metrics.descent;
32869 }
32870 IT_APPLY_FACE_BOX(it, face);
32871
32872
32873
32874 if (face->overline_p)
32875 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32876 take_vertical_position_into_account (it);
32877 if (it->ascent < 0)
32878 it->ascent = 0;
32879 if (it->descent < 0)
32880 it->descent = 0;
32881
32882 if (it->glyph_row)
32883 append_composite_glyph (it);
32884 }
32885 else if (it->what == IT_GLYPHLESS)
32886 produce_glyphless_glyph (it, false, Qnil);
32887 else if (it->what == IT_IMAGE)
32888 produce_image_glyph (it);
32889 else if (it->what == IT_STRETCH)
32890 produce_stretch_glyph (it);
32891 else if (it->what == IT_XWIDGET)
32892 produce_xwidget_glyph (it);
32893
32894 done:
32895
32896
32897 eassert (it->ascent >= 0 && it->descent >= 0);
32898 if (it->area == TEXT_AREA)
32899 it->current_x += it->pixel_width;
32900
32901 if (extra_line_spacing > 0)
32902 {
32903 it->descent += extra_line_spacing;
32904 if (extra_line_spacing > it->max_extra_line_spacing)
32905 it->max_extra_line_spacing = extra_line_spacing;
32906 }
32907
32908 it->max_ascent = max (it->max_ascent, it->ascent);
32909 it->max_descent = max (it->max_descent, it->descent);
32910 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32911 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32912 }
32913
32914
32915
32916
32917
32918
32919 void
32920 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32921 struct glyph *start, enum glyph_row_area updated_area, int len)
32922 {
32923 int x, hpos, chpos = w->phys_cursor.hpos;
32924
32925 eassert (updated_row);
32926
32927
32928
32929 if (!updated_row->reversed_p && chpos < 0)
32930 chpos = 0;
32931 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32932 chpos = updated_row->used[TEXT_AREA] - 1;
32933
32934 block_input ();
32935
32936
32937
32938 hpos = start - updated_row->glyphs[updated_area];
32939 x = draw_glyphs (w, w->output_cursor.x,
32940 updated_row, updated_area,
32941 hpos, hpos + len,
32942 DRAW_NORMAL_TEXT, 0);
32943
32944
32945 if (updated_area == TEXT_AREA
32946 && w->phys_cursor_on_p
32947 && w->phys_cursor.vpos == w->output_cursor.vpos
32948 && chpos >= hpos
32949 && chpos < hpos + len)
32950 w->phys_cursor_on_p = false;
32951
32952 unblock_input ();
32953
32954
32955 w->output_cursor.hpos += len;
32956 w->output_cursor.x = x;
32957 }
32958
32959
32960
32961
32962
32963 void
32964 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32965 struct glyph *start, enum glyph_row_area updated_area, int len)
32966 {
32967 struct frame *f;
32968 int line_height, shift_by_width, shifted_region_width;
32969 struct glyph_row *row;
32970 struct glyph *glyph;
32971 int frame_x, frame_y;
32972 ptrdiff_t hpos;
32973
32974 eassert (updated_row);
32975 block_input ();
32976 f = XFRAME (WINDOW_FRAME (w));
32977
32978
32979 row = updated_row;
32980 line_height = row->height;
32981
32982
32983 shift_by_width = 0;
32984 for (glyph = start; glyph < start + len; ++glyph)
32985 shift_by_width += glyph->pixel_width;
32986
32987
32988 shifted_region_width = (window_box_width (w, updated_area)
32989 - w->output_cursor.x
32990 - shift_by_width);
32991
32992
32993 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32994 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32995
32996 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32997 line_height, shift_by_width);
32998
32999
33000 hpos = start - row->glyphs[updated_area];
33001 draw_glyphs (w, w->output_cursor.x, row, updated_area,
33002 hpos, hpos + len,
33003 DRAW_NORMAL_TEXT, 0);
33004
33005
33006 w->output_cursor.hpos += len;
33007 w->output_cursor.x += shift_by_width;
33008 unblock_input ();
33009 }
33010
33011
33012
33013
33014
33015
33016
33017
33018
33019
33020 void
33021 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
33022 enum glyph_row_area updated_area, int to_x)
33023 {
33024 struct frame *f;
33025 int max_x, min_y, max_y;
33026 int from_x, from_y, to_y;
33027 struct face *face;
33028
33029 eassert (updated_row);
33030 f = XFRAME (w->frame);
33031 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
33032
33033 if (updated_row->full_width_p)
33034 max_x = (WINDOW_PIXEL_WIDTH (w)
33035 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
33036 else
33037 max_x = window_box_width (w, updated_area);
33038 max_y = window_text_bottom_y (w);
33039
33040
33041
33042 if (to_x == 0)
33043 return;
33044 else if (to_x < 0)
33045 to_x = max_x;
33046 else
33047 to_x = min (to_x, max_x);
33048
33049 to_y = min (max_y, w->output_cursor.y + updated_row->height);
33050
33051
33052 if (!updated_row->full_width_p)
33053 notice_overwritten_cursor (w, updated_area,
33054 w->output_cursor.x, -1,
33055 updated_row->y,
33056 MATRIX_ROW_BOTTOM_Y (updated_row));
33057
33058 from_x = w->output_cursor.x;
33059
33060
33061 if (updated_row->full_width_p)
33062 {
33063 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
33064 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
33065 }
33066 else
33067 {
33068 int area_left = window_box_left (w, updated_area);
33069 from_x += area_left;
33070 to_x += area_left;
33071 }
33072
33073 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
33074 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
33075 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
33076
33077
33078 if (to_x > from_x && to_y > from_y)
33079 {
33080 block_input ();
33081 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
33082 to_x - from_x, to_y - from_y);
33083
33084 if (face && !updated_row->stipple_p)
33085 updated_row->stipple_p = face->stipple;
33086 unblock_input ();
33087 }
33088 }
33089
33090 #endif
33091
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102 static enum text_cursor_kinds
33103 get_specified_cursor_type (Lisp_Object arg, int *width)
33104 {
33105 enum text_cursor_kinds type;
33106
33107 if (NILP (arg))
33108 return NO_CURSOR;
33109
33110 if (EQ (arg, Qbox))
33111 return FILLED_BOX_CURSOR;
33112
33113 if (EQ (arg, Qhollow))
33114 return HOLLOW_BOX_CURSOR;
33115
33116 if (EQ (arg, Qbar))
33117 {
33118 *width = 2;
33119 return BAR_CURSOR;
33120 }
33121
33122 if (EQ (arg, Qhbar))
33123 {
33124 *width = 2;
33125 return HBAR_CURSOR;
33126 }
33127
33128 if (CONSP (arg)
33129 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
33130 {
33131 *width = XFIXNUM (XCDR (arg));
33132
33133 if (EQ (XCAR (arg), Qbox))
33134 return FILLED_BOX_CURSOR;
33135 else if (EQ (XCAR (arg), Qbar))
33136 return BAR_CURSOR;
33137 else if (EQ (XCAR (arg), Qhbar))
33138 return HBAR_CURSOR;
33139 }
33140
33141
33142
33143
33144 type = HOLLOW_BOX_CURSOR;
33145
33146 return type;
33147 }
33148
33149
33150 void
33151 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
33152 {
33153 int width = 1;
33154 Lisp_Object tem;
33155
33156 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
33157 FRAME_CURSOR_WIDTH (f) = width;
33158
33159
33160
33161 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
33162 if (!NILP (tem))
33163 {
33164 FRAME_BLINK_OFF_CURSOR (f)
33165 = get_specified_cursor_type (XCDR (tem), &width);
33166 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
33167 }
33168 else
33169 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
33170
33171
33172 f->cursor_type_changed = true;
33173 }
33174
33175
33176 #ifdef HAVE_WINDOW_SYSTEM
33177
33178
33179
33180
33181
33182
33183
33184
33185
33186
33187
33188
33189 static enum text_cursor_kinds
33190 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
33191 bool *active_cursor)
33192 {
33193 struct frame *f = XFRAME (w->frame);
33194 struct buffer *b = XBUFFER (w->contents);
33195 int cursor_type = DEFAULT_CURSOR;
33196 Lisp_Object alt_cursor;
33197 bool non_selected = false;
33198
33199 *active_cursor = true;
33200
33201
33202 if (cursor_in_echo_area
33203 && FRAME_HAS_MINIBUF_P (f)
33204 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
33205 {
33206 if (w == XWINDOW (echo_area_window))
33207 {
33208 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
33209 {
33210 *width = FRAME_CURSOR_WIDTH (f);
33211 return FRAME_DESIRED_CURSOR (f);
33212 }
33213 else
33214 return get_specified_cursor_type (BVAR (b, cursor_type), width);
33215 }
33216
33217 *active_cursor = false;
33218 non_selected = true;
33219 }
33220
33221
33222 else if (w != XWINDOW (f->selected_window)
33223 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
33224 {
33225 *active_cursor = false;
33226
33227 if (MINI_WINDOW_P (w) &&
33228 (minibuf_level == 0
33229 || is_minibuffer (0, w->contents)))
33230 return NO_CURSOR;
33231
33232 non_selected = true;
33233 }
33234
33235
33236 if (NILP (BVAR (b, cursor_type)))
33237 return NO_CURSOR;
33238
33239
33240 if (EQ (BVAR (b, cursor_type), Qt))
33241 {
33242 cursor_type = FRAME_DESIRED_CURSOR (f);
33243 *width = FRAME_CURSOR_WIDTH (f);
33244 }
33245 else
33246 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
33247
33248
33249
33250 if (non_selected)
33251 {
33252 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
33253 if (!EQ (Qt, alt_cursor))
33254 return get_specified_cursor_type (alt_cursor, width);
33255
33256 if (cursor_type == FILLED_BOX_CURSOR)
33257 cursor_type = HOLLOW_BOX_CURSOR;
33258 else if (cursor_type == BAR_CURSOR && *width > 1)
33259 --*width;
33260 return cursor_type;
33261 }
33262
33263
33264 if (!w->cursor_off_p)
33265 {
33266 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
33267 return NO_CURSOR;
33268 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
33269 {
33270 if (cursor_type == FILLED_BOX_CURSOR)
33271 {
33272
33273
33274
33275
33276 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
33277 if (img != NULL && IMAGEP (img->spec))
33278 {
33279
33280
33281
33282
33283
33284
33285 if (!img->mask
33286 || (CONSP (BVAR (b, cursor_type))
33287 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33288 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33289 cursor_type = HOLLOW_BOX_CURSOR;
33290 }
33291 }
33292 else if (cursor_type != NO_CURSOR)
33293 {
33294
33295
33296
33297 cursor_type = HOLLOW_BOX_CURSOR;
33298 }
33299 }
33300 return cursor_type;
33301 }
33302
33303
33304
33305
33306 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33307 return get_specified_cursor_type (XCDR (alt_cursor), width);
33308
33309
33310 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33311 {
33312 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33313 return FRAME_BLINK_OFF_CURSOR (f);
33314 }
33315
33316 #if false
33317
33318
33319
33320
33321
33322
33323
33324
33325
33326
33327 if (cursor_type == FILLED_BOX_CURSOR)
33328 return HOLLOW_BOX_CURSOR;
33329
33330 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33331 {
33332 *width = 1;
33333 return cursor_type;
33334 }
33335 #endif
33336
33337 return NO_CURSOR;
33338 }
33339
33340
33341
33342
33343
33344
33345
33346
33347
33348 static void
33349 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33350 int x0, int x1, int y0, int y1)
33351 {
33352 int cx0, cx1, cy0, cy1;
33353 struct glyph_row *row;
33354
33355 if (!w->phys_cursor_on_p)
33356 return;
33357 if (area != TEXT_AREA)
33358 return;
33359
33360 if (w->phys_cursor.vpos < 0
33361 || w->phys_cursor.vpos >= w->current_matrix->nrows
33362 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33363 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33364 return;
33365
33366 if (row->cursor_in_fringe_p)
33367 {
33368 row->cursor_in_fringe_p = false;
33369 draw_fringe_bitmap (w, row, row->reversed_p);
33370 w->phys_cursor_on_p = false;
33371 return;
33372 }
33373
33374 cx0 = w->phys_cursor.x;
33375 cx1 = cx0 + w->phys_cursor_width;
33376 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33377 return;
33378
33379
33380
33381
33382
33383
33384
33385
33386
33387
33388
33389
33390
33391
33392
33393
33394
33395 cy0 = w->phys_cursor.y;
33396 cy1 = cy0 + w->phys_cursor_height;
33397 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33398 return;
33399
33400 w->phys_cursor_on_p = false;
33401 }
33402
33403 #endif
33404
33405
33406
33407
33408
33409
33410 #ifdef HAVE_WINDOW_SYSTEM
33411
33412
33413
33414
33415
33416 void
33417 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33418 enum glyph_row_area area, int overlaps)
33419 {
33420 int i, x;
33421
33422 block_input ();
33423
33424 x = 0;
33425 for (i = 0; i < row->used[area];)
33426 {
33427 if (row->glyphs[area][i].overlaps_vertically_p)
33428 {
33429 int start = i, start_x = x;
33430
33431 do
33432 {
33433 x += row->glyphs[area][i].pixel_width;
33434 ++i;
33435 }
33436 while (i < row->used[area]
33437 && row->glyphs[area][i].overlaps_vertically_p);
33438
33439 draw_glyphs (w, start_x, row, area,
33440 start, i,
33441 DRAW_NORMAL_TEXT, overlaps);
33442 }
33443 else
33444 {
33445 x += row->glyphs[area][i].pixel_width;
33446 ++i;
33447 }
33448 }
33449
33450 unblock_input ();
33451 }
33452
33453
33454
33455
33456
33457
33458 void
33459 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33460 enum draw_glyphs_face hl)
33461 {
33462
33463
33464
33465 if ((row->reversed_p
33466 ? (w->phys_cursor.hpos >= 0)
33467 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33468 {
33469 bool on_p = w->phys_cursor_on_p;
33470 int x1;
33471 int hpos = w->phys_cursor.hpos;
33472
33473
33474
33475
33476 if (!row->reversed_p && hpos < 0)
33477 hpos = 0;
33478 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33479 hpos = row->used[TEXT_AREA] - 1;
33480
33481 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33482 hl, 0);
33483 w->phys_cursor_on_p = on_p;
33484
33485 if (hl == DRAW_CURSOR)
33486 w->phys_cursor_width = x1 - w->phys_cursor.x;
33487
33488
33489
33490 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33491 {
33492 w->phys_cursor_width = x1 - w->phys_cursor.x;
33493
33494 if (row > w->current_matrix->rows
33495 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33496 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33497 OVERLAPS_ERASED_CURSOR);
33498
33499 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33500 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33501 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33502 OVERLAPS_ERASED_CURSOR);
33503 }
33504 }
33505 }
33506
33507
33508
33509
33510 void
33511 erase_phys_cursor (struct window *w)
33512 {
33513 struct frame *f = XFRAME (w->frame);
33514 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33515 int hpos = w->phys_cursor.hpos;
33516 int vpos = w->phys_cursor.vpos;
33517 bool mouse_face_here_p = false;
33518 struct glyph_matrix *active_glyphs = w->current_matrix;
33519 struct glyph_row *cursor_row;
33520 struct glyph *cursor_glyph;
33521 enum draw_glyphs_face hl;
33522
33523
33524
33525 if (w->phys_cursor_type == NO_CURSOR)
33526 goto mark_cursor_off;
33527
33528
33529
33530 if (vpos >= active_glyphs->nrows)
33531 goto mark_cursor_off;
33532
33533
33534
33535 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33536 if (!cursor_row->enabled_p)
33537 goto mark_cursor_off;
33538
33539
33540
33541 cursor_row->visible_height = min (cursor_row->visible_height,
33542 window_text_bottom_y (w) - cursor_row->y);
33543
33544
33545
33546
33547 if (cursor_row->visible_height <= 0)
33548 goto mark_cursor_off;
33549
33550
33551 if (cursor_row->cursor_in_fringe_p)
33552 {
33553 cursor_row->cursor_in_fringe_p = false;
33554 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33555 goto mark_cursor_off;
33556 }
33557
33558
33559
33560
33561
33562
33563 if ((cursor_row->reversed_p
33564 ? (w->phys_cursor.hpos < 0)
33565 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33566 goto mark_cursor_off;
33567
33568
33569
33570
33571 if (!cursor_row->reversed_p && hpos < 0)
33572 hpos = 0;
33573 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33574 hpos = cursor_row->used[TEXT_AREA] - 1;
33575
33576
33577
33578 if (! NILP (hlinfo->mouse_face_window)
33579 && coords_in_mouse_face_p (w, hpos, vpos)
33580
33581
33582
33583 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33584 mouse_face_here_p = true;
33585
33586 #ifdef HAVE_WINDOW_SYSTEM
33587
33588
33589
33590
33591 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33592 {
33593 w->phys_cursor_on_p = false;
33594 w->phys_cursor_type = NO_CURSOR;
33595 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33596 return;
33597 }
33598 #endif
33599
33600
33601 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33602 {
33603 int x, y;
33604 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33605 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33606 int width;
33607
33608 cursor_glyph = get_phys_cursor_glyph (w);
33609 if (cursor_glyph == NULL)
33610 goto mark_cursor_off;
33611
33612 width = cursor_glyph->pixel_width;
33613 x = w->phys_cursor.x;
33614 if (x < 0)
33615 {
33616 width += x;
33617 x = 0;
33618 }
33619 width = min (width, window_box_width (w, TEXT_AREA) - x);
33620 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33621 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33622
33623 if (width > 0)
33624 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33625 }
33626
33627
33628 if (mouse_face_here_p)
33629 hl = DRAW_MOUSE_FACE;
33630 else
33631 hl = DRAW_NORMAL_TEXT;
33632 draw_phys_cursor_glyph (w, cursor_row, hl);
33633
33634 mark_cursor_off:
33635 w->phys_cursor_on_p = false;
33636 w->phys_cursor_type = NO_CURSOR;
33637 }
33638
33639
33640
33641
33642
33643
33644 void
33645 display_and_set_cursor (struct window *w, bool on,
33646 int hpos, int vpos, int x, int y)
33647 {
33648 struct frame *f = XFRAME (w->frame);
33649 int new_cursor_type;
33650 int new_cursor_width UNINIT;
33651 bool active_cursor;
33652 struct glyph_row *glyph_row;
33653 struct glyph *glyph;
33654
33655
33656
33657
33658
33659 if (! FRAME_REDISPLAY_P (f)
33660 || vpos >= w->current_matrix->nrows
33661 || hpos >= w->current_matrix->matrix_w)
33662 return;
33663
33664
33665 if (!on && !w->phys_cursor_on_p)
33666 return;
33667
33668 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33669
33670
33671 if (!glyph_row->enabled_p)
33672 {
33673 w->phys_cursor_on_p = false;
33674 return;
33675 }
33676
33677
33678
33679
33680
33681
33682
33683
33684
33685 if (FRAME_GARBAGED_P (f))
33686 {
33687 if (on)
33688 {
33689 w->phys_cursor.x = x;
33690 w->phys_cursor.y = glyph_row->y;
33691 w->phys_cursor.hpos = hpos;
33692 w->phys_cursor.vpos = vpos;
33693 }
33694 return;
33695 }
33696
33697 glyph = NULL;
33698 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33699 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33700
33701 eassert (input_blocked_p ());
33702
33703
33704 new_cursor_type = get_window_cursor_type (w, glyph,
33705 &new_cursor_width, &active_cursor);
33706
33707
33708
33709
33710 if (w->phys_cursor_on_p
33711 && (!on
33712 || w->phys_cursor.x != x
33713 || w->phys_cursor.y != y
33714
33715
33716
33717 || hpos < 0
33718 || new_cursor_type != w->phys_cursor_type
33719 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33720 && new_cursor_width != w->phys_cursor_width)))
33721 erase_phys_cursor (w);
33722
33723
33724
33725
33726
33727
33728 if (on)
33729 {
33730 w->phys_cursor_ascent = glyph_row->ascent;
33731 w->phys_cursor_height = glyph_row->height;
33732
33733
33734
33735 w->phys_cursor.x = x;
33736 w->phys_cursor.y = glyph_row->y;
33737 w->phys_cursor.hpos = hpos;
33738 w->phys_cursor.vpos = vpos;
33739 }
33740
33741 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33742 new_cursor_type, new_cursor_width,
33743 on, active_cursor);
33744 }
33745
33746
33747
33748
33749
33750 static void
33751 update_window_cursor (struct window *w, bool on)
33752 {
33753
33754
33755 if (w->current_matrix)
33756 {
33757 int hpos = w->phys_cursor.hpos;
33758 int vpos = w->phys_cursor.vpos;
33759 struct glyph_row *row;
33760
33761 if (vpos >= w->current_matrix->nrows
33762 || hpos >= w->current_matrix->matrix_w)
33763 return;
33764
33765 row = MATRIX_ROW (w->current_matrix, vpos);
33766
33767
33768
33769
33770 if (!row->reversed_p && hpos < 0)
33771 hpos = 0;
33772 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33773 hpos = row->used[TEXT_AREA] - 1;
33774
33775 block_input ();
33776 display_and_set_cursor (w, on, hpos, vpos,
33777 w->phys_cursor.x, w->phys_cursor.y);
33778 unblock_input ();
33779 }
33780 }
33781
33782
33783
33784
33785
33786 static void
33787 update_cursor_in_window_tree (struct window *w, bool on_p)
33788 {
33789 while (w)
33790 {
33791 if (WINDOWP (w->contents))
33792 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33793 else
33794 update_window_cursor (w, on_p);
33795
33796 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33797 }
33798 }
33799
33800
33801
33802
33803
33804
33805 void
33806 gui_update_cursor (struct frame *f, bool on_p)
33807 {
33808 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33809 }
33810
33811
33812
33813
33814
33815
33816
33817 void
33818 gui_clear_cursor (struct window *w)
33819 {
33820 if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33821 update_window_cursor (w, false);
33822 }
33823
33824 #endif
33825
33826
33827
33828 static void
33829 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33830 int start_hpos, int end_hpos,
33831 enum draw_glyphs_face draw)
33832 {
33833 #ifdef HAVE_WINDOW_SYSTEM
33834 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33835 {
33836 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33837 return;
33838 }
33839 #endif
33840
33841 #ifndef HAVE_ANDROID
33842 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33843 #endif
33844 }
33845
33846
33847
33848 static void
33849 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33850 {
33851
33852
33853 if (!WINDOWP (hlinfo->mouse_face_window))
33854 return;
33855
33856 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33857 struct frame *f = XFRAME (WINDOW_FRAME (w));
33858
33859
33860 if (f != hlinfo->mouse_face_mouse_frame)
33861 return;
33862
33863 if (
33864
33865 w->current_matrix != NULL
33866
33867 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33868
33869
33870 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33871 {
33872 bool phys_cursor_on_p = w->phys_cursor_on_p;
33873 #ifdef HAVE_WINDOW_SYSTEM
33874 int mouse_off = 0;
33875 #endif
33876 struct glyph_row *row, *first, *last;
33877
33878 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33879 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33880
33881 for (row = first; row <= last && row->enabled_p; ++row)
33882 {
33883 int start_hpos, end_hpos, start_x;
33884
33885
33886 if (row == first)
33887 {
33888
33889
33890
33891
33892 if (!row->reversed_p)
33893 {
33894 start_hpos = hlinfo->mouse_face_beg_col;
33895 start_x = hlinfo->mouse_face_beg_x;
33896 }
33897 else if (row == last)
33898 {
33899 start_hpos = hlinfo->mouse_face_end_col;
33900 start_x = hlinfo->mouse_face_end_x;
33901 }
33902 else
33903 {
33904 start_hpos = 0;
33905 start_x = 0;
33906 }
33907 }
33908 else if (row->reversed_p && row == last)
33909 {
33910 start_hpos = hlinfo->mouse_face_end_col;
33911 start_x = hlinfo->mouse_face_end_x;
33912 }
33913 else
33914 {
33915 start_hpos = 0;
33916 start_x = 0;
33917 }
33918
33919 if (row == last)
33920 {
33921 if (!row->reversed_p)
33922 end_hpos = hlinfo->mouse_face_end_col;
33923 else if (row == first)
33924 end_hpos = hlinfo->mouse_face_beg_col;
33925 else
33926 {
33927 end_hpos = row->used[TEXT_AREA];
33928 if (draw == DRAW_NORMAL_TEXT)
33929 row->fill_line_p = true;
33930 }
33931 }
33932 else if (row->reversed_p && row == first)
33933 end_hpos = hlinfo->mouse_face_beg_col;
33934 else
33935 {
33936 end_hpos = row->used[TEXT_AREA];
33937 if (draw == DRAW_NORMAL_TEXT)
33938 row->fill_line_p = true;
33939 }
33940
33941 if (end_hpos > start_hpos)
33942 {
33943 draw_row_with_mouse_face (w, start_x, row,
33944 start_hpos, end_hpos, draw);
33945
33946 row->mouse_face_p
33947 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33948 }
33949 #ifdef HAVE_WINDOW_SYSTEM
33950
33951 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33952
33953
33954 && !w->pseudo_window_p
33955 && draw == DRAW_MOUSE_FACE)
33956 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33957 #endif
33958 }
33959
33960
33961
33962 if (FRAME_WINDOW_P (f)
33963 && phys_cursor_on_p && !w->phys_cursor_on_p)
33964 {
33965 #ifdef HAVE_WINDOW_SYSTEM
33966 int hpos = w->phys_cursor.hpos;
33967 int old_phys_cursor_x = w->phys_cursor.x;
33968
33969
33970
33971
33972 if (!row->reversed_p && hpos < 0)
33973 hpos = 0;
33974 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33975 hpos = row->used[TEXT_AREA] - 1;
33976
33977 block_input ();
33978 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33979 w->phys_cursor.x + mouse_off,
33980 w->phys_cursor.y);
33981
33982
33983 w->phys_cursor.x = old_phys_cursor_x;
33984 unblock_input ();
33985 #endif
33986 }
33987 }
33988
33989 #ifdef HAVE_WINDOW_SYSTEM
33990
33991 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33992 {
33993 if (draw == DRAW_NORMAL_TEXT
33994 #ifndef HAVE_EXT_TOOL_BAR
33995 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33996 #endif
33997 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33998 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
33999 else
34000 if (draw == DRAW_MOUSE_FACE)
34001 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
34002 else
34003 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
34004 }
34005 #endif
34006 }
34007
34008
34009
34010
34011
34012
34013 bool
34014 clear_mouse_face (Mouse_HLInfo *hlinfo)
34015 {
34016 bool cleared
34017 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
34018 if (cleared)
34019 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
34020 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
34021 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
34022 hlinfo->mouse_face_window = Qnil;
34023 hlinfo->mouse_face_overlay = Qnil;
34024 return cleared;
34025 }
34026
34027
34028
34029 static bool
34030 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
34031 {
34032 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
34033
34034
34035 if (!(WINDOWP (hlinfo->mouse_face_window)
34036 && XWINDOW (hlinfo->mouse_face_window) == w))
34037 return false;
34038 if (vpos < hlinfo->mouse_face_beg_row
34039 || vpos > hlinfo->mouse_face_end_row)
34040 return false;
34041 if (vpos > hlinfo->mouse_face_beg_row
34042 && vpos < hlinfo->mouse_face_end_row)
34043 return true;
34044
34045 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
34046 {
34047 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34048 {
34049 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
34050 return true;
34051 }
34052 else if ((vpos == hlinfo->mouse_face_beg_row
34053 && hpos >= hlinfo->mouse_face_beg_col)
34054 || (vpos == hlinfo->mouse_face_end_row
34055 && hpos < hlinfo->mouse_face_end_col))
34056 return true;
34057 }
34058 else
34059 {
34060 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
34061 {
34062 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
34063 return true;
34064 }
34065 else if ((vpos == hlinfo->mouse_face_beg_row
34066 && hpos <= hlinfo->mouse_face_beg_col)
34067 || (vpos == hlinfo->mouse_face_end_row
34068 && hpos > hlinfo->mouse_face_end_col))
34069 return true;
34070 }
34071 return false;
34072 }
34073
34074
34075
34076
34077
34078 bool
34079 cursor_in_mouse_face_p (struct window *w)
34080 {
34081 int vpos = w->phys_cursor.vpos;
34082
34083
34084
34085 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
34086 return false;
34087
34088 int hpos = w->phys_cursor.hpos;
34089 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
34090
34091
34092
34093
34094 if (!row->reversed_p && hpos < 0)
34095 hpos = 0;
34096 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
34097 hpos = row->used[TEXT_AREA] - 1;
34098
34099 return coords_in_mouse_face_p (w, hpos, vpos);
34100 }
34101
34102
34103
34104
34105
34106
34107
34108
34109
34110 static void
34111 rows_from_pos_range (struct window *w,
34112 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
34113 Lisp_Object disp_string,
34114 struct glyph_row **start, struct glyph_row **end)
34115 {
34116 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34117 int last_y = window_text_bottom_y (w);
34118 struct glyph_row *row;
34119
34120 *start = NULL;
34121 *end = NULL;
34122
34123 while (!first->enabled_p
34124 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
34125 first++;
34126
34127
34128 for (row = first;
34129 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
34130 row++)
34131 {
34132
34133
34134
34135 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
34136 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
34137
34138
34139
34140
34141 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
34142 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
34143 && !row->ends_at_zv_p
34144 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
34145 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
34146 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
34147 && !row->ends_at_zv_p
34148 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
34149 {
34150
34151
34152
34153
34154
34155
34156
34157
34158
34159
34160 struct glyph *g = row->glyphs[TEXT_AREA];
34161 struct glyph *e = g + row->used[TEXT_AREA];
34162
34163 while (g < e)
34164 {
34165 if (((BUFFERP (g->object) || NILP (g->object))
34166 && start_charpos <= g->charpos && g->charpos < end_charpos)
34167
34168
34169 || EQ (g->object, disp_string))
34170 *start = row;
34171 g++;
34172 }
34173 if (*start)
34174 break;
34175 }
34176 }
34177
34178
34179 if (!*start
34180
34181
34182 && !(row->enabled_p
34183 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
34184 row = first;
34185 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
34186 {
34187 struct glyph_row *next = row + 1;
34188 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
34189
34190 if (!next->enabled_p
34191 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
34192
34193
34194
34195 || (start_charpos < next_start
34196 && end_charpos < next_start)
34197 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
34198 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
34199 && !next->ends_at_zv_p
34200 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
34201 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
34202 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
34203 && !next->ends_at_zv_p
34204 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
34205 {
34206 *end = row;
34207 break;
34208 }
34209 else
34210 {
34211
34212
34213
34214 struct glyph *g = next->glyphs[TEXT_AREA];
34215 struct glyph *s = g;
34216 struct glyph *e = g + next->used[TEXT_AREA];
34217
34218 while (g < e)
34219 {
34220 if (((BUFFERP (g->object) || NILP (g->object))
34221 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
34222
34223
34224
34225
34226
34227 || (((!next->reversed_p && g == s)
34228 || (next->reversed_p && g == e - 1))
34229 && (g->charpos == end_charpos
34230
34231
34232 || (g->charpos == -1
34233 && !row->ends_at_zv_p
34234 && next_start == end_charpos)))))
34235
34236
34237 || EQ (g->object, disp_string))
34238 break;
34239 g++;
34240 }
34241 if (g == e)
34242 {
34243 *end = row;
34244 break;
34245 }
34246
34247
34248 else if (next->ends_at_zv_p)
34249 {
34250 *end = next;
34251 break;
34252 }
34253 }
34254 }
34255 }
34256
34257
34258
34259
34260
34261
34262
34263
34264
34265
34266 static void
34267 mouse_face_from_buffer_pos (Lisp_Object window,
34268 Mouse_HLInfo *hlinfo,
34269 ptrdiff_t mouse_charpos,
34270 ptrdiff_t start_charpos,
34271 ptrdiff_t end_charpos,
34272 Lisp_Object before_string,
34273 Lisp_Object after_string,
34274 Lisp_Object disp_string)
34275 {
34276 struct window *w = XWINDOW (window);
34277 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34278 struct glyph_row *r1, *r2;
34279 struct glyph *glyph, *end;
34280 ptrdiff_t ignore, pos;
34281 int x;
34282
34283 eassert (NILP (disp_string) || STRINGP (disp_string));
34284 eassert (NILP (before_string) || STRINGP (before_string));
34285 eassert (NILP (after_string) || STRINGP (after_string));
34286
34287
34288 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
34289 if (r1 == NULL)
34290 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34291
34292
34293 if (!NILP (before_string) || !NILP (disp_string))
34294 {
34295 struct glyph_row *prev;
34296 while ((prev = r1 - 1, prev >= first)
34297 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34298 && prev->used[TEXT_AREA] > 0)
34299 {
34300 struct glyph *beg = prev->glyphs[TEXT_AREA];
34301 glyph = beg + prev->used[TEXT_AREA];
34302 while (--glyph >= beg && NILP (glyph->object));
34303 if (glyph < beg
34304 || !(EQ (glyph->object, before_string)
34305 || EQ (glyph->object, disp_string)))
34306 break;
34307 r1 = prev;
34308 }
34309 }
34310 if (r2 == NULL)
34311 {
34312 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34313 hlinfo->mouse_face_past_end = true;
34314 }
34315 else if (!NILP (after_string))
34316 {
34317
34318 struct glyph_row *next;
34319 struct glyph_row *last
34320 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34321
34322 for (next = r2 + 1;
34323 next <= last
34324 && next->used[TEXT_AREA] > 0
34325 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34326 ++next)
34327 r2 = next;
34328 }
34329
34330
34331
34332
34333
34334 if (r1->y > r2->y)
34335 {
34336 struct glyph_row *tem = r2;
34337
34338 r2 = r1;
34339 r1 = tem;
34340 }
34341
34342 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34343 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34344
34345
34346
34347
34348
34349
34350
34351
34352
34353
34354
34355 if (!r1->reversed_p)
34356 {
34357
34358
34359 glyph = r1->glyphs[TEXT_AREA];
34360 end = glyph + r1->used[TEXT_AREA];
34361 x = r1->x;
34362
34363
34364 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34365 for (; glyph < end
34366 && NILP (glyph->object)
34367 && glyph->charpos < 0;
34368 ++glyph)
34369 x += glyph->pixel_width;
34370
34371
34372
34373
34374 for (; glyph < end
34375 && !NILP (glyph->object)
34376 && !EQ (glyph->object, disp_string)
34377 && !(BUFFERP (glyph->object)
34378 && (glyph->charpos >= start_charpos
34379 && glyph->charpos < end_charpos));
34380 ++glyph)
34381 {
34382
34383
34384
34385 if (EQ (glyph->object, before_string))
34386 {
34387 pos = string_buffer_position (before_string,
34388 start_charpos);
34389
34390
34391 if (!pos || (pos >= start_charpos && pos < end_charpos))
34392 break;
34393 }
34394 else if (EQ (glyph->object, after_string))
34395 {
34396 pos = string_buffer_position (after_string, end_charpos);
34397 if (!pos || (pos >= start_charpos && pos < end_charpos))
34398 break;
34399 }
34400 x += glyph->pixel_width;
34401 }
34402 hlinfo->mouse_face_beg_x = x;
34403 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34404 }
34405 else
34406 {
34407
34408
34409 struct glyph *g;
34410
34411 end = r1->glyphs[TEXT_AREA] - 1;
34412 glyph = end + r1->used[TEXT_AREA];
34413
34414
34415 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34416 for (; glyph > end
34417 && NILP (glyph->object)
34418 && glyph->charpos < 0;
34419 --glyph)
34420 ;
34421
34422
34423
34424
34425 for (; glyph > end
34426 && !NILP (glyph->object)
34427 && !EQ (glyph->object, disp_string)
34428 && !(BUFFERP (glyph->object)
34429 && (glyph->charpos >= start_charpos
34430 && glyph->charpos < end_charpos));
34431 --glyph)
34432 {
34433
34434
34435
34436 if (EQ (glyph->object, before_string))
34437 {
34438 pos = string_buffer_position (before_string, start_charpos);
34439
34440
34441 if (!pos || (pos >= start_charpos && pos < end_charpos))
34442 break;
34443 }
34444 else if (EQ (glyph->object, after_string))
34445 {
34446 pos = string_buffer_position (after_string, end_charpos);
34447 if (!pos || (pos >= start_charpos && pos < end_charpos))
34448 break;
34449 }
34450 }
34451
34452 glyph++;
34453 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34454 x += g->pixel_width;
34455 hlinfo->mouse_face_beg_x = x;
34456 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34457 }
34458
34459
34460
34461
34462 if (r2 != r1)
34463 {
34464 if (!r2->reversed_p)
34465 {
34466 glyph = r2->glyphs[TEXT_AREA];
34467 end = glyph + r2->used[TEXT_AREA];
34468 x = r2->x;
34469 }
34470 else
34471 {
34472 end = r2->glyphs[TEXT_AREA] - 1;
34473 glyph = end + r2->used[TEXT_AREA];
34474 }
34475 }
34476
34477 if (!r2->reversed_p)
34478 {
34479
34480
34481
34482 while (end > glyph
34483 && NILP ((end - 1)->object))
34484 --end;
34485
34486
34487
34488
34489 for (--end;
34490 end > glyph
34491 && !NILP (end->object)
34492 && !EQ (end->object, disp_string)
34493 && !(BUFFERP (end->object)
34494 && (end->charpos >= start_charpos
34495 && end->charpos < end_charpos));
34496 --end)
34497 {
34498
34499
34500
34501 if (EQ (end->object, before_string))
34502 {
34503 pos = string_buffer_position (before_string, start_charpos);
34504 if (!pos || (pos >= start_charpos && pos < end_charpos))
34505 break;
34506 }
34507 else if (EQ (end->object, after_string))
34508 {
34509 pos = string_buffer_position (after_string, end_charpos);
34510 if (!pos || (pos >= start_charpos && pos < end_charpos))
34511 break;
34512 }
34513 }
34514
34515 for (; glyph <= end; ++glyph)
34516 x += glyph->pixel_width;
34517
34518 hlinfo->mouse_face_end_x = x;
34519 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34520 }
34521 else
34522 {
34523
34524
34525
34526 x = r2->x;
34527 end++;
34528 while (end < glyph
34529 && NILP (end->object))
34530 {
34531 x += end->pixel_width;
34532 ++end;
34533 }
34534
34535
34536
34537
34538 for ( ;
34539 end < glyph
34540 && !NILP (end->object)
34541 && !EQ (end->object, disp_string)
34542 && !(BUFFERP (end->object)
34543 && (end->charpos >= start_charpos
34544 && end->charpos < end_charpos));
34545 ++end)
34546 {
34547
34548
34549
34550 if (EQ (end->object, before_string))
34551 {
34552 pos = string_buffer_position (before_string, start_charpos);
34553 if (!pos || (pos >= start_charpos && pos < end_charpos))
34554 break;
34555 }
34556 else if (EQ (end->object, after_string))
34557 {
34558 pos = string_buffer_position (after_string, end_charpos);
34559 if (!pos || (pos >= start_charpos && pos < end_charpos))
34560 break;
34561 }
34562 x += end->pixel_width;
34563 }
34564
34565
34566
34567
34568
34569 if (end == glyph
34570 && BUFFERP (end->object)
34571 && (end->charpos < start_charpos
34572 || end->charpos >= end_charpos))
34573 {
34574 x += end->pixel_width;
34575 ++end;
34576 }
34577 hlinfo->mouse_face_end_x = x;
34578 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34579 }
34580
34581 hlinfo->mouse_face_window = window;
34582 hlinfo->mouse_face_face_id
34583 = face_at_buffer_position (w, mouse_charpos, &ignore,
34584 mouse_charpos + 1,
34585 !hlinfo->mouse_face_hidden, -1, 0);
34586 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34587 }
34588
34589
34590
34591
34592
34593 #if false
34594
34595
34596
34597
34598
34599
34600
34601
34602
34603
34604
34605
34606
34607
34608
34609
34610 static bool
34611 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34612 int *hpos, int *vpos, int *x, int *y, bool right_p)
34613 {
34614 int yb = window_text_bottom_y (w);
34615 struct glyph_row *r;
34616 struct glyph *best_glyph = NULL;
34617 struct glyph_row *best_row = NULL;
34618 int best_x = 0;
34619
34620 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34621 r->enabled_p && r->y < yb;
34622 ++r)
34623 {
34624 struct glyph *g = r->glyphs[TEXT_AREA];
34625 struct glyph *e = g + r->used[TEXT_AREA];
34626 int gx;
34627
34628 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34629 if (EQ (g->object, object))
34630 {
34631 if (g->charpos == pos)
34632 {
34633 best_glyph = g;
34634 best_x = gx;
34635 best_row = r;
34636 goto found;
34637 }
34638 else if (best_glyph == NULL
34639 || ((eabs (g->charpos - pos)
34640 < eabs (best_glyph->charpos - pos))
34641 && (right_p
34642 ? g->charpos < pos
34643 : g->charpos > pos)))
34644 {
34645 best_glyph = g;
34646 best_x = gx;
34647 best_row = r;
34648 }
34649 }
34650 }
34651
34652 found:
34653
34654 if (best_glyph)
34655 {
34656 *x = best_x;
34657 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34658
34659 if (right_p)
34660 {
34661 *x += best_glyph->pixel_width;
34662 ++*hpos;
34663 }
34664
34665 *y = best_row->y;
34666 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34667 }
34668
34669 return best_glyph != NULL;
34670 }
34671 #endif
34672
34673
34674
34675
34676
34677
34678 static void
34679 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34680 Lisp_Object object,
34681 ptrdiff_t startpos, ptrdiff_t endpos)
34682 {
34683 int yb = window_text_bottom_y (w);
34684 struct glyph_row *r;
34685 struct glyph *g, *e;
34686 int gx;
34687 bool found = false;
34688
34689
34690
34691
34692 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34693 r->enabled_p && r->y < yb;
34694 ++r)
34695 {
34696 if (!r->reversed_p)
34697 {
34698 g = r->glyphs[TEXT_AREA];
34699 e = g + r->used[TEXT_AREA];
34700 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34701 if (EQ (g->object, object)
34702 && startpos <= g->charpos && g->charpos < endpos)
34703 {
34704 hlinfo->mouse_face_beg_row
34705 = MATRIX_ROW_VPOS (r, w->current_matrix);
34706 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34707 hlinfo->mouse_face_beg_x = gx;
34708 found = true;
34709 break;
34710 }
34711 }
34712 else
34713 {
34714 struct glyph *g1;
34715
34716 e = r->glyphs[TEXT_AREA];
34717 g = e + r->used[TEXT_AREA];
34718 for ( ; g > e; --g)
34719 if (EQ ((g-1)->object, object)
34720 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34721 {
34722 hlinfo->mouse_face_beg_row
34723 = MATRIX_ROW_VPOS (r, w->current_matrix);
34724 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34725 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34726 gx += g1->pixel_width;
34727 hlinfo->mouse_face_beg_x = gx;
34728 found = true;
34729 break;
34730 }
34731 }
34732 if (found)
34733 break;
34734 }
34735
34736 if (!found)
34737 return;
34738
34739
34740
34741 for (++r; r->enabled_p && r->y < yb; ++r)
34742 {
34743 g = r->glyphs[TEXT_AREA];
34744 e = g + r->used[TEXT_AREA];
34745 found = false;
34746 for ( ; g < e; ++g)
34747 if (EQ (g->object, object)
34748 && startpos <= g->charpos && g->charpos < endpos)
34749 {
34750 found = true;
34751 break;
34752 }
34753 if (!found)
34754 break;
34755 }
34756
34757
34758 r--;
34759
34760
34761 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34762
34763
34764
34765 if (!r->reversed_p)
34766 {
34767 g = r->glyphs[TEXT_AREA];
34768 e = g + r->used[TEXT_AREA];
34769 for ( ; e > g; --e)
34770 if (EQ ((e-1)->object, object)
34771 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34772 break;
34773 hlinfo->mouse_face_end_col = e - g;
34774
34775 for (gx = r->x; g < e; ++g)
34776 gx += g->pixel_width;
34777 hlinfo->mouse_face_end_x = gx;
34778 }
34779 else
34780 {
34781 e = r->glyphs[TEXT_AREA];
34782 g = e + r->used[TEXT_AREA];
34783 for (gx = r->x ; e < g; ++e)
34784 {
34785 if (EQ (e->object, object)
34786 && startpos <= e->charpos && e->charpos < endpos)
34787 break;
34788 gx += e->pixel_width;
34789 }
34790 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34791 hlinfo->mouse_face_end_x = gx;
34792 }
34793 }
34794
34795 #ifdef HAVE_WINDOW_SYSTEM
34796
34797
34798
34799 static bool
34800 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34801 {
34802 if (!CONSP (hot_spot))
34803 return false;
34804
34805 if (EQ (XCAR (hot_spot), Qrect))
34806 {
34807
34808 Lisp_Object rect = XCDR (hot_spot);
34809 Lisp_Object tem;
34810 if (!CONSP (rect))
34811 return false;
34812 if (!CONSP (XCAR (rect)))
34813 return false;
34814 if (!CONSP (XCDR (rect)))
34815 return false;
34816 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34817 return false;
34818 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34819 return false;
34820 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34821 return false;
34822 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34823 return false;
34824 return true;
34825 }
34826 else if (EQ (XCAR (hot_spot), Qcircle))
34827 {
34828
34829 Lisp_Object circ = XCDR (hot_spot);
34830 Lisp_Object lr, lx0, ly0;
34831 if (CONSP (circ)
34832 && CONSP (XCAR (circ))
34833 && (lr = XCDR (circ), NUMBERP (lr))
34834 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34835 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34836 {
34837 double r = XFLOATINT (lr);
34838 double dx = XFIXNUM (lx0) - x;
34839 double dy = XFIXNUM (ly0) - y;
34840 return (dx * dx + dy * dy <= r * r);
34841 }
34842 }
34843 else if (EQ (XCAR (hot_spot), Qpoly))
34844 {
34845
34846 if (VECTORP (XCDR (hot_spot)))
34847 {
34848 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34849 Lisp_Object *poly = v->contents;
34850 ptrdiff_t n = v->header.size;
34851 ptrdiff_t i;
34852 bool inside = false;
34853 Lisp_Object lx, ly;
34854 int x0, y0;
34855
34856
34857 if (n < 6 || n & 1)
34858 return false;
34859
34860
34861
34862
34863
34864 if ((lx = poly[n-2], !FIXNUMP (lx))
34865 || (ly = poly[n-1], !FIXNUMP (lx)))
34866 return false;
34867 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34868 for (i = 0; i < n; i += 2)
34869 {
34870 int x1 = x0, y1 = y0;
34871 if ((lx = poly[i], !FIXNUMP (lx))
34872 || (ly = poly[i+1], !FIXNUMP (ly)))
34873 return false;
34874 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34875
34876
34877 if (x0 >= x)
34878 {
34879 if (x1 >= x)
34880 continue;
34881 }
34882 else if (x1 < x)
34883 continue;
34884 if (y > y0 && y > y1)
34885 continue;
34886 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34887 inside = !inside;
34888 }
34889 return inside;
34890 }
34891 }
34892 return false;
34893 }
34894
34895 Lisp_Object
34896 find_hot_spot (Lisp_Object map, int x, int y)
34897 {
34898 while (CONSP (map))
34899 {
34900 if (CONSP (XCAR (map))
34901 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34902 return XCAR (map);
34903 map = XCDR (map);
34904 }
34905
34906 return Qnil;
34907 }
34908
34909 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34910 3, 3, 0,
34911 doc:
34912
34913
34914
34915
34916
34917
34918
34919
34920 )
34921 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34922 {
34923 if (NILP (map))
34924 return Qnil;
34925
34926 CHECK_FIXNUM (x);
34927 CHECK_FIXNUM (y);
34928
34929 return find_hot_spot (map,
34930 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34931 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34932 }
34933 #endif
34934
34935
34936
34937 static void
34938 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34939 {
34940 #ifdef HAVE_WINDOW_SYSTEM
34941 if (!FRAME_WINDOW_P (f))
34942 return;
34943
34944
34945 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34946 || EQ (track_mouse, Qdrag_source))
34947 return;
34948
34949 if (!NILP (pointer))
34950 {
34951 if (EQ (pointer, Qarrow))
34952 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34953 else if (EQ (pointer, Qhand))
34954 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34955 else if (EQ (pointer, Qtext))
34956 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34957 else if (EQ (pointer, intern ("hdrag")))
34958 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34959 else if (EQ (pointer, intern ("nhdrag")))
34960 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34961 # ifdef HAVE_X_WINDOWS
34962 else if (EQ (pointer, intern ("vdrag")))
34963 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34964 # endif
34965 else if (EQ (pointer, intern ("hourglass")))
34966 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34967 else if (EQ (pointer, Qmodeline))
34968 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34969 else
34970 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34971 }
34972
34973 if (cursor != No_Cursor)
34974 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34975 #endif
34976 }
34977
34978
34979
34980
34981
34982
34983
34984 static void
34985 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34986 enum window_part area)
34987 {
34988 struct window *w = XWINDOW (window);
34989 struct frame *f = XFRAME (w->frame);
34990 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34991 Emacs_Cursor cursor = No_Cursor;
34992 Lisp_Object pointer = Qnil;
34993 int dx, dy, width, height;
34994 ptrdiff_t charpos;
34995 Lisp_Object string, object = Qnil;
34996 Lisp_Object pos UNINIT;
34997 Lisp_Object mouse_face;
34998 int original_x_pixel = x;
34999 struct glyph * glyph = NULL, * row_start_glyph = NULL;
35000 struct glyph_row *row UNINIT;
35001
35002 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
35003 {
35004 int x0;
35005 struct glyph *end;
35006
35007
35008
35009 string = mode_line_string (w, area, &x, &y, &charpos,
35010 &object, &dx, &dy, &width, &height);
35011
35012 row = (area == ON_MODE_LINE
35013 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
35014 : (area == ON_TAB_LINE
35015 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
35016 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
35017
35018
35019 if (row->mode_line_p && row->enabled_p)
35020 {
35021 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
35022 end = glyph + row->used[TEXT_AREA];
35023
35024 for (x0 = original_x_pixel;
35025 glyph < end && x0 >= glyph->pixel_width;
35026 ++glyph)
35027 x0 -= glyph->pixel_width;
35028
35029 if (glyph >= end)
35030 glyph = NULL;
35031 }
35032 }
35033 else
35034 {
35035 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
35036
35037
35038 string = marginal_area_string (w, area, &x, &y, &charpos,
35039 &object, &dx, &dy, &width, &height);
35040 }
35041
35042 Lisp_Object help = Qnil;
35043
35044 #ifdef HAVE_WINDOW_SYSTEM
35045 if (IMAGEP (object))
35046 {
35047 Lisp_Object image_map, hotspot;
35048 if ((image_map = plist_get (XCDR (object), QCmap),
35049 !NILP (image_map))
35050 && (hotspot = find_hot_spot (image_map, dx, dy),
35051 CONSP (hotspot))
35052 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35053 {
35054 Lisp_Object plist;
35055
35056
35057
35058
35059 hotspot = XCDR (hotspot);
35060 if (CONSP (hotspot)
35061 && (plist = XCAR (hotspot), CONSP (plist)))
35062 {
35063 pointer = plist_get (plist, Qpointer);
35064 if (NILP (pointer))
35065 pointer = Qhand;
35066 help = plist_get (plist, Qhelp_echo);
35067 if (!NILP (help))
35068 {
35069 help_echo_string = help;
35070 XSETWINDOW (help_echo_window, w);
35071 help_echo_object = w->contents;
35072 help_echo_pos = charpos;
35073 }
35074 }
35075 }
35076 if (NILP (pointer))
35077 pointer = plist_get (XCDR (object), QCpointer);
35078 }
35079 #endif
35080
35081
35082
35083
35084 if (STRINGP (string))
35085 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
35086
35087
35088
35089
35090
35091 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
35092 || area == ON_TAB_LINE)
35093 {
35094
35095
35096 if (NILP (help))
35097 {
35098 if (STRINGP (string))
35099 help = Fget_text_property (pos, Qhelp_echo, string);
35100
35101 if (!NILP (help))
35102 {
35103 help_echo_string = help;
35104 XSETWINDOW (help_echo_window, w);
35105 help_echo_object = string;
35106 help_echo_pos = charpos;
35107 }
35108 else if (area == ON_MODE_LINE
35109 && !NILP (w->mode_line_help_echo))
35110 {
35111 help_echo_string = w->mode_line_help_echo;
35112 XSETWINDOW (help_echo_window, w);
35113 help_echo_object = Qnil;
35114 help_echo_pos = -1;
35115 }
35116 }
35117
35118 #ifdef HAVE_WINDOW_SYSTEM
35119
35120 if (FRAME_WINDOW_P (f))
35121 {
35122 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
35123 || minibuf_level
35124 || NILP (Vresize_mini_windows));
35125
35126 if (STRINGP (string))
35127 {
35128 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35129
35130 if (NILP (pointer))
35131 pointer = Fget_text_property (pos, Qpointer, string);
35132
35133
35134 if (NILP (pointer)
35135 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
35136 || area == ON_TAB_LINE))
35137 {
35138 Lisp_Object map;
35139
35140 map = Fget_text_property (pos, Qlocal_map, string);
35141 if (!KEYMAPP (map))
35142 map = Fget_text_property (pos, Qkeymap, string);
35143 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
35144 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35145 }
35146 }
35147 else if (draggable && area == ON_MODE_LINE)
35148 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35149 else if ((area == ON_MODE_LINE
35150 && WINDOW_BOTTOMMOST_P (w)
35151 && !FRAME_HAS_MINIBUF_P (f)
35152 && !NILP (Fframe_parameter
35153 (w->frame, Qdrag_with_mode_line)))
35154 || (((area == ON_HEADER_LINE
35155 && !NILP (Fframe_parameter
35156 (w->frame, Qdrag_with_header_line)))
35157 || (area == ON_TAB_LINE
35158 && !NILP (Fframe_parameter
35159 (w->frame, Qdrag_with_tab_line))))
35160 && WINDOW_TOPMOST_P (w)))
35161 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35162 else
35163 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35164 }
35165 #endif
35166 }
35167
35168
35169 bool mouse_face_shown = false;
35170
35171 if (STRINGP (string))
35172 {
35173 mouse_face = Fget_text_property (pos, Qmouse_face, string);
35174 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
35175 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
35176 || (area == ON_TAB_LINE))
35177 && glyph)
35178 {
35179 Lisp_Object b, e;
35180
35181 struct glyph * tmp_glyph;
35182
35183 int gpos;
35184 int gseq_length;
35185 int total_pixel_width;
35186 ptrdiff_t begpos, endpos, ignore;
35187
35188 int vpos, hpos;
35189
35190 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
35191 Qmouse_face, string, Qnil);
35192 if (NILP (b))
35193 begpos = 0;
35194 else
35195 begpos = XFIXNUM (b);
35196
35197 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
35198 if (NILP (e))
35199 endpos = SCHARS (string);
35200 else
35201 endpos = XFIXNUM (e);
35202
35203
35204
35205
35206
35207
35208
35209
35210
35211
35212
35213 tmp_glyph = row_start_glyph;
35214 while (tmp_glyph < glyph
35215 && (!(EQ (tmp_glyph->object, glyph->object)
35216 && begpos <= tmp_glyph->charpos
35217 && tmp_glyph->charpos < endpos)))
35218 tmp_glyph++;
35219 gpos = glyph - tmp_glyph;
35220
35221
35222
35223
35224
35225
35226 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
35227 tmp_glyph > glyph
35228 && (!(EQ (tmp_glyph->object, glyph->object)
35229 && begpos <= tmp_glyph->charpos
35230 && tmp_glyph->charpos < endpos));
35231 tmp_glyph--)
35232 ;
35233 gseq_length = gpos + (tmp_glyph - glyph) + 1;
35234
35235
35236
35237 total_pixel_width = 0;
35238 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
35239 total_pixel_width += tmp_glyph->pixel_width;
35240
35241
35242
35243
35244 hpos = x - gpos;
35245 vpos = (area == ON_MODE_LINE
35246 ? (w->current_matrix)->nrows - 1
35247 : (area == ON_TAB_LINE
35248 ? 0
35249 : (w->current_matrix->tab_line_p
35250 ? 1
35251 : 0)));
35252
35253
35254
35255 if ( EQ (window, hlinfo->mouse_face_window)
35256 && (!row->reversed_p
35257 ? (hlinfo->mouse_face_beg_col <= hpos
35258 && hpos < hlinfo->mouse_face_end_col)
35259
35260 : (hlinfo->mouse_face_end_col <= hpos
35261 && hpos < hlinfo->mouse_face_beg_col))
35262 && hlinfo->mouse_face_beg_row == vpos )
35263 return;
35264
35265 if (clear_mouse_face (hlinfo))
35266 cursor = No_Cursor;
35267
35268 if (!row->reversed_p)
35269 {
35270 hlinfo->mouse_face_beg_col = hpos;
35271 hlinfo->mouse_face_beg_x = original_x_pixel
35272 - (total_pixel_width + dx);
35273 hlinfo->mouse_face_end_col = hpos + gseq_length;
35274 hlinfo->mouse_face_end_x = 0;
35275 }
35276 else
35277 {
35278
35279
35280 hlinfo->mouse_face_end_col = hpos;
35281 hlinfo->mouse_face_end_x = original_x_pixel
35282 - (total_pixel_width + dx);
35283 hlinfo->mouse_face_beg_col = hpos + gseq_length;
35284 hlinfo->mouse_face_beg_x = 0;
35285 }
35286
35287 hlinfo->mouse_face_beg_row = vpos;
35288 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
35289 hlinfo->mouse_face_past_end = false;
35290 hlinfo->mouse_face_window = window;
35291
35292 hlinfo->mouse_face_face_id =
35293 face_at_string_position (w, string, charpos, 0, &ignore,
35294 glyph->face_id, true, 0);
35295
35296 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35297 mouse_face_shown = true;
35298
35299 if (NILP (pointer))
35300 pointer = Qhand;
35301 }
35302 }
35303
35304
35305
35306 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35307 || area == ON_TAB_LINE) && !mouse_face_shown)
35308 clear_mouse_face (hlinfo);
35309
35310 define_frame_cursor1 (f, cursor, pointer);
35311 }
35312
35313
35314
35315
35316
35317
35318
35319
35320
35321
35322 void
35323 note_mouse_highlight (struct frame *f, int x, int y)
35324 {
35325 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35326 enum window_part part = ON_NOTHING;
35327 Lisp_Object window;
35328 struct window *w;
35329 Emacs_Cursor cursor = No_Cursor;
35330 Lisp_Object pointer = Qnil;
35331 struct buffer *b;
35332
35333
35334 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS) \
35335 || defined (HAVE_ANDROID)
35336 if (popup_activated ())
35337 return;
35338 #endif
35339
35340 #if defined (HAVE_HAIKU)
35341 if (popup_activated_p)
35342 return;
35343 #endif
35344
35345 if (!f->glyphs_initialized_p
35346 || f->pointer_invisible)
35347 return;
35348
35349 hlinfo->mouse_face_mouse_x = x;
35350 hlinfo->mouse_face_mouse_y = y;
35351 hlinfo->mouse_face_mouse_frame = f;
35352
35353 if (hlinfo->mouse_face_defer)
35354 return;
35355
35356
35357 window = window_from_coordinates (f, x, y, &part, true, true);
35358
35359
35360 if (! EQ (window, hlinfo->mouse_face_window)
35361
35362 || (!NILP (hlinfo->mouse_face_window)
35363 && !NILP (window)
35364 && part != ON_TEXT
35365 && part != ON_MODE_LINE
35366 && part != ON_HEADER_LINE
35367 && part != ON_TAB_LINE))
35368 clear_mouse_face (hlinfo);
35369
35370
35371 help_echo_string = Qnil;
35372
35373
35374 if (!FRAME_WINDOW_P (f)
35375 && (y >= FRAME_MENU_BAR_LINES (f)
35376 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35377 {
35378 int prop_idx;
35379 bool ignore;
35380 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35381
35382 if (!NILP (caption))
35383 {
35384 help_echo_object = help_echo_window = Qnil;
35385 help_echo_pos = -1;
35386 help_echo_string = AREF (f->tab_bar_items,
35387 prop_idx * TAB_BAR_ITEM_NSLOTS
35388 + TAB_BAR_ITEM_HELP);
35389 if (NILP (help_echo_string))
35390 help_echo_string = caption;
35391 }
35392 }
35393
35394 #ifdef HAVE_WINDOW_SYSTEM
35395
35396
35397 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35398 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35399 {
35400 enum internal_border_part part = frame_internal_border_part (f, x, y);
35401
35402 switch (part)
35403 {
35404 case INTERNAL_BORDER_NONE:
35405 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35406
35407 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35408 break;
35409 case INTERNAL_BORDER_LEFT_EDGE:
35410 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35411 break;
35412 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35413 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35414 break;
35415 case INTERNAL_BORDER_TOP_EDGE:
35416 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35417 break;
35418 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35419 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35420 break;
35421 case INTERNAL_BORDER_RIGHT_EDGE:
35422 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35423 break;
35424 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35425 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35426 break;
35427 case INTERNAL_BORDER_BOTTOM_EDGE:
35428 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35429 break;
35430 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35431 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35432 break;
35433 default:
35434
35435 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35436 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35437 }
35438
35439 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35440 {
35441
35442 help_echo_string = build_string ("drag-mouse-1: resize frame");
35443 goto set_cursor;
35444 }
35445 }
35446 #endif
35447
35448
35449 if (!WINDOWP (window))
35450 return;
35451
35452
35453 w = XWINDOW (window);
35454 frame_to_window_pixel_xy (w, &x, &y);
35455
35456 #if defined (HAVE_WINDOW_SYSTEM)
35457
35458
35459 if (EQ (window, f->tab_bar_window))
35460 {
35461 note_tab_bar_highlight (f, x, y);
35462 if (tab_bar__dragging_in_progress)
35463 {
35464 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35465 goto set_cursor;
35466 }
35467 else
35468 return;
35469 }
35470 else
35471 {
35472
35473
35474
35475
35476 f->last_tab_bar_item = -1;
35477 }
35478 #endif
35479
35480 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35481
35482
35483 if (EQ (window, f->tool_bar_window))
35484 {
35485 note_tool_bar_highlight (f, x, y);
35486 return;
35487 }
35488 #endif
35489
35490
35491 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35492 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35493 {
35494 note_mode_line_or_margin_highlight (window, x, y, part);
35495
35496 #ifdef HAVE_WINDOW_SYSTEM
35497 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35498 {
35499 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35500
35501 goto set_cursor;
35502 }
35503 else
35504 #endif
35505 return;
35506 }
35507
35508 #ifdef HAVE_WINDOW_SYSTEM
35509 if (part == ON_VERTICAL_BORDER)
35510 {
35511 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35512 help_echo_string = build_string ("drag-mouse-1: resize");
35513 goto set_cursor;
35514 }
35515 else if (part == ON_RIGHT_DIVIDER)
35516 {
35517 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35518 help_echo_string = build_string ("drag-mouse-1: resize");
35519 goto set_cursor;
35520 }
35521 else if (part == ON_BOTTOM_DIVIDER)
35522 if (! WINDOW_BOTTOMMOST_P (w)
35523 || minibuf_level
35524 || NILP (Vresize_mini_windows))
35525 {
35526 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35527 help_echo_string = build_string ("drag-mouse-1: resize");
35528 goto set_cursor;
35529 }
35530 else
35531 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35532 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35533 || part == ON_VERTICAL_SCROLL_BAR
35534 || part == ON_HORIZONTAL_SCROLL_BAR)
35535 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35536 else
35537 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35538 #endif
35539
35540
35541
35542 b = XBUFFER (w->contents);
35543 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35544 {
35545 int hpos, vpos, dx, dy, area = LAST_AREA;
35546 ptrdiff_t pos;
35547 struct glyph *glyph;
35548 Lisp_Object object;
35549 Lisp_Object mouse_face = Qnil, position;
35550 Lisp_Object *overlay_vec = NULL;
35551 ptrdiff_t i, noverlays;
35552 struct buffer *obuf;
35553 ptrdiff_t obegv, ozv;
35554 bool same_region;
35555
35556
35557 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35558
35559 #ifdef HAVE_WINDOW_SYSTEM
35560
35561 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35562 {
35563 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35564 if (img != NULL && IMAGEP (img->spec))
35565 {
35566 Lisp_Object image_map, hotspot;
35567 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35568 !NILP (image_map))
35569 && (hotspot = find_hot_spot (image_map,
35570 glyph->slice.img.x + dx,
35571 glyph->slice.img.y + dy),
35572 CONSP (hotspot))
35573 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35574 {
35575 Lisp_Object plist;
35576
35577
35578
35579
35580
35581 hotspot = XCDR (hotspot);
35582 if (CONSP (hotspot)
35583 && (plist = XCAR (hotspot), CONSP (plist)))
35584 {
35585 pointer = plist_get (plist, Qpointer);
35586 if (NILP (pointer))
35587 pointer = Qhand;
35588 help_echo_string = plist_get (plist, Qhelp_echo);
35589 if (!NILP (help_echo_string))
35590 {
35591 help_echo_window = window;
35592 help_echo_object = glyph->object;
35593 help_echo_pos = glyph->charpos;
35594 }
35595 }
35596 }
35597 if (NILP (pointer))
35598 pointer = plist_get (XCDR (img->spec), QCpointer);
35599 }
35600 }
35601 #endif
35602
35603
35604 if (glyph == NULL
35605 || area != TEXT_AREA
35606 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35607
35608
35609
35610
35611
35612 || NILP (glyph->object)
35613
35614
35615
35616
35617 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35618 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35619 && glyph->type == STRETCH_GLYPH
35620 && glyph->avoid_cursor_p))
35621 {
35622 if (clear_mouse_face (hlinfo))
35623 cursor = No_Cursor;
35624 if (FRAME_WINDOW_P (f) && NILP (pointer))
35625 {
35626 #ifdef HAVE_WINDOW_SYSTEM
35627 if (area != TEXT_AREA)
35628 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35629 else
35630 pointer = Vvoid_text_area_pointer;
35631 #endif
35632 }
35633 goto set_cursor;
35634 }
35635
35636 pos = glyph->charpos;
35637 object = glyph->object;
35638 if (!STRINGP (object) && !BUFFERP (object))
35639 goto set_cursor;
35640
35641
35642 if (BUFFERP (object) && pos > BUF_Z (b))
35643 goto set_cursor;
35644
35645
35646
35647 obuf = current_buffer;
35648 current_buffer = b;
35649 obegv = BEGV;
35650 ozv = ZV;
35651 BEGV = BEG;
35652 ZV = Z;
35653
35654
35655 position = make_fixnum (pos);
35656
35657 USE_SAFE_ALLOCA;
35658
35659 if (BUFFERP (object))
35660 {
35661
35662 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35663
35664 noverlays = sort_overlays (overlay_vec, noverlays, w);
35665 }
35666 else
35667 noverlays = 0;
35668
35669 if (NILP (Vmouse_highlight))
35670 {
35671 clear_mouse_face (hlinfo);
35672 goto check_help_echo;
35673 }
35674
35675 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35676
35677 if (same_region)
35678 cursor = No_Cursor;
35679
35680
35681 if (! same_region
35682
35683
35684
35685
35686
35687 || (!hlinfo->mouse_face_hidden
35688 && OVERLAYP (hlinfo->mouse_face_overlay)
35689
35690 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35691 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35692 {
35693
35694 Lisp_Object overlay = Qnil;
35695 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35696 {
35697 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35698 if (!NILP (mouse_face))
35699 overlay = overlay_vec[i];
35700 }
35701
35702
35703
35704 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35705 goto check_help_echo;
35706
35707
35708 if (clear_mouse_face (hlinfo))
35709 cursor = No_Cursor;
35710
35711
35712 hlinfo->mouse_face_overlay = overlay;
35713
35714
35715 if (NILP (overlay))
35716 mouse_face = Fget_text_property (position, Qmouse_face, object);
35717
35718
35719
35720 if (!NILP (mouse_face) && STRINGP (object))
35721 {
35722
35723
35724 Lisp_Object s, e;
35725 ptrdiff_t ignore;
35726
35727 s = Fprevious_single_property_change
35728 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35729 e = Fnext_single_property_change
35730 (position, Qmouse_face, object, Qnil);
35731 if (NILP (s))
35732 s = make_fixnum (0);
35733 if (NILP (e))
35734 e = make_fixnum (SCHARS (object));
35735 mouse_face_from_string_pos (w, hlinfo, object,
35736 XFIXNUM (s), XFIXNUM (e));
35737 hlinfo->mouse_face_past_end = false;
35738 hlinfo->mouse_face_window = window;
35739 hlinfo->mouse_face_face_id
35740 = face_at_string_position (w, object, pos, 0, &ignore,
35741 glyph->face_id, true, 0);
35742 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35743 cursor = No_Cursor;
35744 }
35745 else
35746 {
35747
35748
35749 Lisp_Object buffer UNINIT;
35750 Lisp_Object disp_string UNINIT;
35751
35752 if (STRINGP (object))
35753 {
35754
35755
35756 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35757 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35758 pos = string_buffer_position (object, start);
35759 if (pos > 0)
35760 {
35761 mouse_face = get_char_property_and_overlay
35762 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35763 buffer = w->contents;
35764 disp_string = object;
35765 }
35766 }
35767 else
35768 {
35769 buffer = object;
35770 disp_string = Qnil;
35771 }
35772
35773 if (!NILP (mouse_face))
35774 {
35775 Lisp_Object before, after;
35776 Lisp_Object before_string, after_string;
35777
35778
35779
35780
35781
35782
35783
35784
35785
35786
35787 Lisp_Object lim1
35788 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35789 ? Fmarker_position (w->start)
35790 : Qnil;
35791 Lisp_Object lim2
35792 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35793 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35794 - w->window_end_pos)
35795 : Qnil;
35796
35797 if (NILP (overlay))
35798 {
35799
35800 before = Fprevious_single_property_change
35801 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35802 after = Fnext_single_property_change
35803 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35804 before_string = after_string = Qnil;
35805 }
35806 else
35807 {
35808
35809 before = Foverlay_start (overlay);
35810 after = Foverlay_end (overlay);
35811 before_string = Foverlay_get (overlay, Qbefore_string);
35812 after_string = Foverlay_get (overlay, Qafter_string);
35813
35814 if (!STRINGP (before_string)) before_string = Qnil;
35815 if (!STRINGP (after_string)) after_string = Qnil;
35816 }
35817
35818 mouse_face_from_buffer_pos (window, hlinfo, pos,
35819 NILP (before)
35820 ? 1
35821 : XFIXNAT (before),
35822 NILP (after)
35823 ? BUF_Z (XBUFFER (buffer))
35824 : XFIXNAT (after),
35825 before_string, after_string,
35826 disp_string);
35827 cursor = No_Cursor;
35828 }
35829 }
35830 }
35831
35832 check_help_echo:
35833
35834
35835 if (NILP (help_echo_string)) {
35836 Lisp_Object help, overlay;
35837
35838
35839 help = overlay = Qnil;
35840 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35841 {
35842 overlay = overlay_vec[i];
35843 help = Foverlay_get (overlay, Qhelp_echo);
35844 }
35845
35846 if (!NILP (help))
35847 {
35848 help_echo_string = help;
35849 help_echo_window = window;
35850 help_echo_object = overlay;
35851 help_echo_pos = pos;
35852 }
35853 else
35854 {
35855 Lisp_Object obj = glyph->object;
35856 ptrdiff_t charpos = glyph->charpos;
35857
35858
35859 if (STRINGP (obj)
35860 && charpos >= 0
35861 && charpos < SCHARS (obj))
35862 {
35863 help = Fget_text_property (make_fixnum (charpos),
35864 Qhelp_echo, obj);
35865 if (NILP (help))
35866 {
35867
35868
35869 struct glyph_row *r
35870 = MATRIX_ROW (w->current_matrix, vpos);
35871 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35872 ptrdiff_t p = string_buffer_position (obj, start);
35873 if (p > 0)
35874 {
35875 help = Fget_char_property (make_fixnum (p),
35876 Qhelp_echo, w->contents);
35877 if (!NILP (help))
35878 {
35879 charpos = p;
35880 obj = w->contents;
35881 }
35882 }
35883 }
35884 }
35885 else if (BUFFERP (obj)
35886 && charpos >= BEGV
35887 && charpos < ZV)
35888 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35889 obj);
35890
35891 if (!NILP (help))
35892 {
35893 help_echo_string = help;
35894 help_echo_window = window;
35895 help_echo_object = obj;
35896 help_echo_pos = charpos;
35897 }
35898 }
35899 }
35900
35901 #ifdef HAVE_WINDOW_SYSTEM
35902
35903 if (FRAME_WINDOW_P (f) && NILP (pointer))
35904 {
35905
35906 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35907 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35908
35909 if (NILP (pointer))
35910 {
35911 Lisp_Object obj = glyph->object;
35912 ptrdiff_t charpos = glyph->charpos;
35913
35914
35915 if (STRINGP (obj)
35916 && charpos >= 0
35917 && charpos < SCHARS (obj))
35918 {
35919 pointer = Fget_text_property (make_fixnum (charpos),
35920 Qpointer, obj);
35921 if (NILP (pointer))
35922 {
35923
35924
35925 struct glyph_row *r
35926 = MATRIX_ROW (w->current_matrix, vpos);
35927 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35928 ptrdiff_t p = string_buffer_position (obj, start);
35929 if (p > 0)
35930 pointer = Fget_char_property (make_fixnum (p),
35931 Qpointer, w->contents);
35932 }
35933 }
35934 else if (BUFFERP (obj)
35935 && charpos >= BEGV
35936 && charpos < ZV)
35937 pointer = Fget_text_property (make_fixnum (charpos),
35938 Qpointer, obj);
35939 }
35940 }
35941 #endif
35942
35943 BEGV = obegv;
35944 ZV = ozv;
35945 current_buffer = obuf;
35946 SAFE_FREE ();
35947 }
35948
35949 set_cursor:
35950 define_frame_cursor1 (f, cursor, pointer);
35951 }
35952
35953
35954
35955
35956
35957
35958
35959 void
35960 gui_clear_window_mouse_face (struct window *w)
35961 {
35962 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35963 Lisp_Object window;
35964
35965 block_input ();
35966 XSETWINDOW (window, w);
35967 if (EQ (window, hlinfo->mouse_face_window))
35968 clear_mouse_face (hlinfo);
35969 unblock_input ();
35970 }
35971
35972
35973
35974
35975
35976
35977 void
35978 cancel_mouse_face (struct frame *f)
35979 {
35980 Lisp_Object window;
35981 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35982
35983 window = hlinfo->mouse_face_window;
35984 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35985 reset_mouse_highlight (hlinfo);
35986 }
35987
35988
35989
35990
35991
35992
35993
35994 #ifdef HAVE_WINDOW_SYSTEM
35995
35996
35997
35998
35999 static void
36000 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
36001 enum glyph_row_area area)
36002 {
36003 struct glyph *first = row->glyphs[area];
36004 struct glyph *end = row->glyphs[area] + row->used[area];
36005 struct glyph *last;
36006 int first_x, start_x, x;
36007
36008 if (area == TEXT_AREA && row->fill_line_p)
36009
36010 draw_glyphs (w, row->x, row, area,
36011 0, row->used[area],
36012 DRAW_NORMAL_TEXT, 0);
36013 else
36014 {
36015
36016
36017
36018 start_x = window_box_left_offset (w, area);
36019 x = start_x;
36020 if (area == TEXT_AREA)
36021 x += row->x;
36022
36023
36024 while (first < end
36025 && x + first->pixel_width < r->x)
36026 {
36027 x += first->pixel_width;
36028 ++first;
36029 }
36030
36031
36032 last = first;
36033 first_x = x;
36034
36035
36036
36037 int r_end = r->x + r->width;
36038 while (last < end && x < r_end)
36039 {
36040 x += last->pixel_width;
36041 ++last;
36042 }
36043
36044
36045 if (last > first)
36046 draw_glyphs (w, first_x - start_x, row, area,
36047 first - row->glyphs[area], last - row->glyphs[area],
36048 DRAW_NORMAL_TEXT, 0);
36049 }
36050 }
36051
36052
36053
36054
36055
36056
36057 static bool
36058 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
36059 {
36060 eassert (row->enabled_p);
36061
36062 if (row->mode_line_p || w->pseudo_window_p)
36063 draw_glyphs (w, 0, row, TEXT_AREA,
36064 0, row->used[TEXT_AREA],
36065 DRAW_NORMAL_TEXT, 0);
36066 else
36067 {
36068 if (row->used[LEFT_MARGIN_AREA])
36069 expose_area (w, row, r, LEFT_MARGIN_AREA);
36070 if (row->used[TEXT_AREA])
36071 expose_area (w, row, r, TEXT_AREA);
36072 if (row->used[RIGHT_MARGIN_AREA])
36073 expose_area (w, row, r, RIGHT_MARGIN_AREA);
36074 draw_row_fringe_bitmaps (w, row);
36075 }
36076
36077 return row->mouse_face_p;
36078 }
36079
36080
36081
36082
36083
36084
36085
36086
36087
36088
36089 static void
36090 expose_overlaps (struct window *w,
36091 struct glyph_row *first_overlapping_row,
36092 struct glyph_row *last_overlapping_row,
36093 const Emacs_Rectangle *r)
36094 {
36095 struct glyph_row *row;
36096
36097 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
36098 if (row->overlapping_p)
36099 {
36100 eassert (row->enabled_p && !row->mode_line_p);
36101
36102 row->clip = r;
36103 if (row->used[LEFT_MARGIN_AREA])
36104 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
36105
36106 if (row->used[TEXT_AREA])
36107 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
36108
36109 if (row->used[RIGHT_MARGIN_AREA])
36110 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
36111 row->clip = NULL;
36112 }
36113 }
36114
36115
36116
36117
36118 static bool
36119 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
36120 {
36121 Emacs_Rectangle cr, result;
36122 struct glyph *cursor_glyph;
36123 struct glyph_row *row;
36124
36125 if (w->phys_cursor.vpos >= 0
36126 && w->phys_cursor.vpos < w->current_matrix->nrows
36127 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
36128 row->enabled_p)
36129 && row->cursor_in_fringe_p)
36130 {
36131
36132 cr.x = window_box_right_offset (w,
36133 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
36134 ? RIGHT_MARGIN_AREA
36135 : TEXT_AREA));
36136 cr.y = row->y;
36137 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
36138 cr.height = row->height;
36139 return gui_intersect_rectangles (&cr, r, &result);
36140 }
36141
36142 cursor_glyph = get_phys_cursor_glyph (w);
36143 if (cursor_glyph)
36144 {
36145
36146
36147 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
36148 cr.y = w->phys_cursor.y;
36149 cr.width = cursor_glyph->pixel_width;
36150 cr.height = w->phys_cursor_height;
36151
36152
36153 return gui_intersect_rectangles (&cr, r, &result);
36154 }
36155
36156 return false;
36157 }
36158
36159
36160
36161
36162
36163
36164 void
36165 gui_draw_vertical_border (struct window *w)
36166 {
36167 struct frame *f = XFRAME (WINDOW_FRAME (w));
36168
36169
36170
36171
36172
36173
36174
36175
36176
36177 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
36178 return;
36179
36180
36181
36182
36183 if (!WINDOW_RIGHTMOST_P (w)
36184 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
36185 {
36186 int x0, x1, y0, y1;
36187
36188 window_box_edges (w, &x0, &y0, &x1, &y1);
36189 y1 -= 1;
36190
36191 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36192 x1 -= 1;
36193
36194 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
36195 }
36196
36197 if (!WINDOW_LEFTMOST_P (w)
36198 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
36199 {
36200 int x0, x1, y0, y1;
36201
36202 window_box_edges (w, &x0, &y0, &x1, &y1);
36203 y1 -= 1;
36204
36205 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
36206 x0 -= 1;
36207
36208 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
36209 }
36210 }
36211
36212
36213
36214
36215 void
36216 gui_draw_right_divider (struct window *w)
36217 {
36218 struct frame *f = WINDOW_XFRAME (w);
36219
36220 if (w->mini || w->pseudo_window_p)
36221 return;
36222 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36223 {
36224 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
36225 int x1 = WINDOW_RIGHT_EDGE_X (w);
36226 int y0 = WINDOW_TOP_EDGE_Y (w);
36227 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36228
36229
36230
36231 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
36232 && !NILP (w->parent)
36233 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
36234 && !NILP (w->next))
36235 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36236
36237 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36238 }
36239 }
36240
36241 static void
36242 gui_draw_bottom_divider (struct window *w)
36243 {
36244 struct frame *f = XFRAME (WINDOW_FRAME (w));
36245
36246 if (w->mini || w->pseudo_window_p)
36247 return;
36248 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36249 {
36250 int x0 = WINDOW_LEFT_EDGE_X (w);
36251 int x1 = WINDOW_RIGHT_EDGE_X (w);
36252 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
36253 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
36254 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
36255
36256
36257
36258 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
36259 && p
36260 && ((WINDOW_VERTICAL_COMBINATION_P (p)
36261 && !NILP (w->next))
36262 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
36263 && NILP (w->next)
36264 && !NILP (p->parent)
36265 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
36266 && !NILP (XWINDOW (p->parent)->next))))
36267 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
36268
36269 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
36270 }
36271 }
36272
36273
36274
36275
36276
36277
36278 static bool
36279 expose_window (struct window *w, const Emacs_Rectangle *fr)
36280 {
36281 struct frame *f = XFRAME (w->frame);
36282 Emacs_Rectangle wr, r;
36283 bool mouse_face_overwritten_p = false;
36284
36285
36286
36287
36288
36289 if (w->current_matrix == NULL)
36290 return false;
36291
36292
36293
36294
36295 if (w->must_be_updated_p)
36296 {
36297 SET_FRAME_GARBAGED (f);
36298 return false;
36299 }
36300
36301
36302 wr.x = WINDOW_LEFT_EDGE_X (w);
36303 wr.y = WINDOW_TOP_EDGE_Y (w);
36304 wr.width = WINDOW_PIXEL_WIDTH (w);
36305 wr.height = WINDOW_PIXEL_HEIGHT (w);
36306
36307 if (gui_intersect_rectangles (fr, &wr, &r))
36308 {
36309 int yb = window_text_bottom_y (w);
36310 struct glyph_row *row;
36311 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36312
36313 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36314 r.x, r.y, r.width, r.height);
36315
36316
36317 r.x -= WINDOW_LEFT_EDGE_X (w);
36318 r.y -= WINDOW_TOP_EDGE_Y (w);
36319
36320
36321 bool cursor_cleared_p = (!w->pseudo_window_p
36322 && phys_cursor_in_rect_p (w, &r));
36323 if (cursor_cleared_p)
36324 gui_clear_cursor (w);
36325
36326
36327
36328
36329
36330
36331 bool phys_cursor_on_p = w->phys_cursor_on_p;
36332
36333
36334
36335
36336 int r_bottom = r.y + r.height;
36337
36338
36339
36340
36341
36342 bool buffer_changed = false;
36343 struct buffer *oldbuf = current_buffer;
36344 if (!w->pseudo_window_p)
36345 {
36346 set_buffer_internal_1 (XBUFFER (w->contents));
36347 buffer_changed = true;
36348 }
36349
36350
36351 first_overlapping_row = last_overlapping_row = NULL;
36352 for (row = w->current_matrix->rows;
36353 row->enabled_p;
36354 ++row)
36355 {
36356 int y0 = row->y;
36357 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36358
36359 if ((y0 >= r.y && y0 < r_bottom)
36360 || (y1 > r.y && y1 < r_bottom)
36361 || (r.y >= y0 && r.y < y1)
36362 || (r_bottom > y0 && r_bottom < y1))
36363 {
36364
36365
36366 if (row->overlapping_p && !row->mode_line_p)
36367 {
36368 if (first_overlapping_row == NULL)
36369 first_overlapping_row = row;
36370 last_overlapping_row = row;
36371 }
36372
36373 row->clip = fr;
36374 if (expose_line (w, row, &r))
36375 mouse_face_overwritten_p = true;
36376 row->clip = NULL;
36377 }
36378 else if (row->overlapping_p)
36379 {
36380
36381 if (y0 < r.y
36382 ? y0 + row->phys_height > r.y
36383 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36384 {
36385 if (first_overlapping_row == NULL)
36386 first_overlapping_row = row;
36387 last_overlapping_row = row;
36388 }
36389 }
36390
36391 if (y1 >= yb)
36392 break;
36393 }
36394
36395 if (buffer_changed)
36396 set_buffer_internal_1 (oldbuf);
36397
36398
36399 if (window_wants_mode_line (w)
36400 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36401 row->enabled_p)
36402 && row->y < r_bottom)
36403 {
36404 if (expose_line (w, row, &r))
36405 mouse_face_overwritten_p = true;
36406 }
36407
36408 if (!w->pseudo_window_p)
36409 {
36410
36411 if (first_overlapping_row)
36412 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36413 fr);
36414
36415
36416 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36417 gui_draw_right_divider (w);
36418 else
36419 gui_draw_vertical_border (w);
36420
36421 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36422 gui_draw_bottom_divider (w);
36423
36424
36425 if (cursor_cleared_p
36426 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36427 update_window_cursor (w, true);
36428 }
36429 }
36430
36431 return mouse_face_overwritten_p;
36432 }
36433
36434
36435
36436
36437
36438
36439
36440 static bool
36441 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36442 {
36443 struct frame *f = XFRAME (w->frame);
36444 bool mouse_face_overwritten_p = false;
36445
36446 while (w && !FRAME_GARBAGED_P (f))
36447 {
36448 mouse_face_overwritten_p
36449 |= (WINDOWP (w->contents)
36450 ? expose_window_tree (XWINDOW (w->contents), r)
36451 : expose_window (w, r));
36452
36453 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36454 }
36455
36456 return mouse_face_overwritten_p;
36457 }
36458
36459
36460
36461
36462
36463
36464
36465
36466 void
36467 expose_frame (struct frame *f, int x, int y, int w, int h)
36468 {
36469 Emacs_Rectangle r;
36470 bool mouse_face_overwritten_p = false;
36471
36472 if (FRAME_GARBAGED_P (f))
36473 {
36474 redisplay_trace ("expose_frame garbaged\n");
36475 return;
36476 }
36477
36478
36479
36480
36481 if (FRAME_FACE_CACHE (f) == NULL
36482 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36483 {
36484 redisplay_trace ("expose_frame no faces\n");
36485 return;
36486 }
36487
36488 if (w == 0 || h == 0)
36489 {
36490 r.x = r.y = 0;
36491 r.width = FRAME_TEXT_WIDTH (f);
36492 r.height = FRAME_TEXT_HEIGHT (f);
36493 }
36494 else
36495 {
36496 r.x = x;
36497 r.y = y;
36498 r.width = w;
36499 r.height = h;
36500 }
36501
36502 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36503 r.x, r.y, r.width, r.height);
36504 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36505
36506 if (WINDOWP (f->tab_bar_window))
36507 mouse_face_overwritten_p
36508 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36509
36510 #ifndef HAVE_EXT_TOOL_BAR
36511 if (WINDOWP (f->tool_bar_window))
36512 mouse_face_overwritten_p
36513 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36514 #endif
36515
36516 #if defined HAVE_WINDOW_SYSTEM && !defined HAVE_EXT_MENU_BAR
36517 if (WINDOWP (f->menu_bar_window))
36518 mouse_face_overwritten_p
36519 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36520 #endif
36521
36522
36523
36524
36525
36526
36527
36528
36529
36530
36531
36532
36533
36534
36535 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36536 {
36537 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36538 if (f == hlinfo->mouse_face_mouse_frame)
36539 {
36540 int mouse_x = hlinfo->mouse_face_mouse_x;
36541 int mouse_y = hlinfo->mouse_face_mouse_y;
36542 clear_mouse_face (hlinfo);
36543 note_mouse_highlight (f, mouse_x, mouse_y);
36544 }
36545 }
36546 }
36547
36548
36549
36550
36551
36552
36553
36554 bool
36555 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36556 Emacs_Rectangle *result)
36557 {
36558 const Emacs_Rectangle *left, *right;
36559 const Emacs_Rectangle *upper, *lower;
36560 bool intersection_p = false;
36561
36562
36563 if (r1->x < r2->x)
36564 left = r1, right = r2;
36565 else
36566 left = r2, right = r1;
36567
36568
36569
36570 if (right->x <= left->x + left->width)
36571 {
36572 result->x = right->x;
36573
36574
36575
36576 result->width = (min (left->x + left->width, right->x + right->width)
36577 - result->x);
36578
36579
36580 if (r1->y < r2->y)
36581 upper = r1, lower = r2;
36582 else
36583 upper = r2, lower = r1;
36584
36585
36586
36587 if (lower->y <= upper->y + upper->height)
36588 {
36589 result->y = lower->y;
36590
36591
36592
36593 result->height = (min (lower->y + lower->height,
36594 upper->y + upper->height)
36595 - result->y);
36596 intersection_p = true;
36597 }
36598 }
36599
36600 return intersection_p;
36601 }
36602
36603
36604
36605
36606
36607
36608 void
36609 gui_union_rectangles (const Emacs_Rectangle *a, const Emacs_Rectangle *b,
36610 Emacs_Rectangle *result)
36611 {
36612 struct gui_box a_box, b_box, result_box;
36613
36614
36615
36616 if (!a->width || !a->height)
36617 {
36618 *result = *b;
36619 return;
36620 }
36621 else if (!b->width || !b->height)
36622 {
36623 *result = *a;
36624 return;
36625 }
36626
36627
36628 a_box.x1 = a->x;
36629 a_box.y1 = a->y;
36630 a_box.x2 = a->x + a->width;
36631 a_box.y2 = a->y + a->height;
36632
36633 b_box.x1 = b->x;
36634 b_box.y1 = b->y;
36635 b_box.x2 = b->x + b->width;
36636 b_box.y2 = b->y + b->height;
36637
36638
36639 result_box.x1 = min (a_box.x1, b_box.x1);
36640 result_box.y1 = min (a_box.y1, b_box.y1);
36641 result_box.x2 = max (a_box.x2, b_box.x2);
36642 result_box.y2 = max (a_box.y2, b_box.y2);
36643
36644
36645
36646 result->x = result_box.x1;
36647 result->y = result_box.y1;
36648 result->width = result_box.x2 - result_box.x1;
36649 result->height = result_box.y2 - result_box.y1;
36650 }
36651
36652 #endif
36653
36654
36655
36656
36657
36658
36659 void
36660 syms_of_xdisp (void)
36661 {
36662 Vwith_echo_area_save_vector = Qnil;
36663 staticpro (&Vwith_echo_area_save_vector);
36664
36665 Vmessage_stack = Qnil;
36666 staticpro (&Vmessage_stack);
36667
36668
36669 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36670
36671 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36672
36673 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36674 scroll_minibuffer_conservatively,
36675 doc:
36676
36677 );
36678 scroll_minibuffer_conservatively = true;
36679
36680 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36681 doc:
36682
36683
36684
36685
36686
36687 );
36688 inhibit_message = false;
36689
36690 message_dolog_marker1 = Fmake_marker ();
36691 staticpro (&message_dolog_marker1);
36692 message_dolog_marker2 = Fmake_marker ();
36693 staticpro (&message_dolog_marker2);
36694 message_dolog_marker3 = Fmake_marker ();
36695 staticpro (&message_dolog_marker3);
36696
36697 defsubr (&Sset_buffer_redisplay);
36698 #ifdef GLYPH_DEBUG
36699 defsubr (&Sdump_frame_glyph_matrix);
36700 defsubr (&Sdump_glyph_matrix);
36701 defsubr (&Sdump_glyph_row);
36702 defsubr (&Sdump_tab_bar_row);
36703 defsubr (&Sdump_tool_bar_row);
36704 defsubr (&Strace_redisplay);
36705 defsubr (&Strace_to_stderr);
36706 #endif
36707 #ifdef HAVE_WINDOW_SYSTEM
36708 defsubr (&Stab_bar_height);
36709 defsubr (&Stool_bar_height);
36710 defsubr (&Slookup_image_map);
36711 #endif
36712 defsubr (&Sline_pixel_height);
36713 defsubr (&Sformat_mode_line);
36714 defsubr (&Sinvisible_p);
36715 defsubr (&Scurrent_bidi_paragraph_direction);
36716 defsubr (&Swindow_text_pixel_size);
36717 defsubr (&Sbuffer_text_pixel_size);
36718 defsubr (&Smove_point_visually);
36719 defsubr (&Sbidi_find_overridden_directionality);
36720 defsubr (&Sdisplay__line_is_continued_p);
36721 defsubr (&Sget_display_property);
36722 defsubr (&Slong_line_optimizations_p);
36723
36724 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36725 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36726 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36727 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36728 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36729 DEFSYM (Qeval, "eval");
36730 DEFSYM (QCdata, ":data");
36731
36732
36733 DEFSYM (Qdisplay, "display");
36734 DEFSYM (Qspace_width, "space-width");
36735 DEFSYM (Qraise, "raise");
36736 DEFSYM (Qslice, "slice");
36737 DEFSYM (Qspace, "space");
36738 DEFSYM (Qmargin, "margin");
36739 DEFSYM (Qpointer, "pointer");
36740 DEFSYM (Qleft_margin, "left-margin");
36741 DEFSYM (Qright_margin, "right-margin");
36742 DEFSYM (Qcenter, "center");
36743 DEFSYM (Qline_height, "line-height");
36744 DEFSYM (QCalign_to, ":align-to");
36745 DEFSYM (QCrelative_width, ":relative-width");
36746 DEFSYM (QCrelative_height, ":relative-height");
36747 DEFSYM (QCeval, ":eval");
36748 DEFSYM (QCpropertize, ":propertize");
36749 DEFSYM (QCfile, ":file");
36750 DEFSYM (Qfontified, "fontified");
36751 DEFSYM (Qfontification_functions, "fontification-functions");
36752 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36753 "long-line-optimizations-in-fontification-functions");
36754
36755
36756
36757 DEFSYM (Qdisable_eval, "disable-eval");
36758
36759
36760 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36761
36762
36763 DEFSYM (Qline_number, "line-number");
36764 DEFSYM (Qline_number_current_line, "line-number-current-line");
36765 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36766 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36767
36768 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36769
36770
36771 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36772
36773
36774 DEFSYM (Qescape_glyph, "escape-glyph");
36775
36776
36777
36778 DEFSYM (Qnobreak_space, "nobreak-space");
36779 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36780
36781
36782
36783 DEFSYM (Qimage, "image");
36784
36785
36786 DEFSYM (Qtext, "text");
36787 DEFSYM (Qboth, "both");
36788 DEFSYM (Qboth_horiz, "both-horiz");
36789 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36790
36791
36792 DEFSYM (QCmap, ":map");
36793 DEFSYM (QCpointer, ":pointer");
36794 DEFSYM (Qrect, "rect");
36795 DEFSYM (Qcircle, "circle");
36796 DEFSYM (Qpoly, "poly");
36797
36798 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36799
36800 DEFSYM (Qgrow_only, "grow-only");
36801 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36802 DEFSYM (Qposition, "position");
36803 DEFSYM (Qbuffer_position, "buffer-position");
36804 DEFSYM (Qobject, "object");
36805
36806
36807 DEFSYM (Qbar, "bar");
36808 DEFSYM (Qhbar, "hbar");
36809 DEFSYM (Qbox, "box");
36810 DEFSYM (Qhollow, "hollow");
36811
36812
36813 DEFSYM (Qhand, "hand");
36814 DEFSYM (Qarrow, "arrow");
36815
36816
36817 DEFSYM (Qdragging, "dragging");
36818 DEFSYM (Qdropping, "dropping");
36819 DEFSYM (Qdrag_source, "drag-source");
36820
36821 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36822 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36823 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36824
36825 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36826
36827 list_of_error = list1 (Qerror);
36828 staticpro (&list_of_error);
36829
36830
36831
36832
36833
36834 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36835 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36836
36837
36838
36839 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36840 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36841
36842 echo_buffer[0] = echo_buffer[1] = Qnil;
36843 staticpro (&echo_buffer[0]);
36844 staticpro (&echo_buffer[1]);
36845
36846 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36847 staticpro (&echo_area_buffer[0]);
36848 staticpro (&echo_area_buffer[1]);
36849
36850 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36851 doc:
36852
36853
36854
36855 );
36856 Vmessages_buffer_name = build_string ("*Messages*");
36857
36858 mode_line_proptrans_alist = Qnil;
36859 staticpro (&mode_line_proptrans_alist);
36860 mode_line_string_list = Qnil;
36861 staticpro (&mode_line_string_list);
36862 mode_line_string_face = Qnil;
36863 staticpro (&mode_line_string_face);
36864 mode_line_string_face_prop = Qnil;
36865 staticpro (&mode_line_string_face_prop);
36866 Vmode_line_unwind_vector = Qnil;
36867 staticpro (&Vmode_line_unwind_vector);
36868
36869 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36870
36871 help_echo_string = Qnil;
36872 staticpro (&help_echo_string);
36873 help_echo_object = Qnil;
36874 staticpro (&help_echo_object);
36875 help_echo_window = Qnil;
36876 staticpro (&help_echo_window);
36877 previous_help_echo_string = Qnil;
36878 staticpro (&previous_help_echo_string);
36879 help_echo_pos = -1;
36880
36881 DEFSYM (Qright_to_left, "right-to-left");
36882 DEFSYM (Qleft_to_right, "left-to-right");
36883 defsubr (&Sbidi_resolved_levels);
36884
36885 #ifdef HAVE_WINDOW_SYSTEM
36886 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36887 doc:
36888
36889 );
36890 x_stretch_cursor_p = 0;
36891 #endif
36892
36893 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36894 doc:
36895 );
36896 Vshow_trailing_whitespace = Qnil;
36897
36898 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36899 doc:
36900
36901
36902 );
36903 Vmode_line_compact = Qnil;
36904 DEFSYM (Qlong, "long");
36905
36906 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36907 doc:
36908
36909
36910
36911
36912
36913
36914
36915
36916
36917
36918
36919 );
36920 Vnobreak_char_display = Qt;
36921
36922 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36923 doc:
36924
36925
36926
36927
36928
36929
36930
36931
36932
36933
36934
36935
36936
36937
36938
36939 );
36940 nobreak_char_ascii_display = false;
36941
36942 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36943 doc:
36944
36945
36946 );
36947 Vvoid_text_area_pointer = Qarrow;
36948
36949 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36950 doc:
36951 );
36952 Vinhibit_redisplay = Qnil;
36953
36954 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36955 doc: );
36956 Vglobal_mode_string = Qnil;
36957
36958 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36959 doc:
36960
36961 );
36962 Voverlay_arrow_position = Qnil;
36963
36964 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36965 doc:
36966 );
36967 Voverlay_arrow_string = build_pure_c_string ("=>");
36968
36969 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36970 doc:
36971
36972 );
36973 Voverlay_arrow_variable_list
36974 = list1 (intern_c_string ("overlay-arrow-position"));
36975
36976 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36977 doc:
36978
36979
36980
36981 );
36982
36983 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36984 doc:
36985
36986
36987
36988
36989
36990
36991
36992
36993
36994 );
36995 scroll_conservatively = 0;
36996
36997 DEFVAR_INT ("scroll-margin", scroll_margin,
36998 doc:
36999
37000 );
37001 scroll_margin = 0;
37002
37003 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
37004 doc:
37005
37006
37007
37008 );
37009 Vmaximum_scroll_margin = make_float (0.25);
37010
37011 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
37012 doc:
37013 );
37014 Vdisplay_pixels_per_inch = make_float (72.0);
37015
37016 #ifdef GLYPH_DEBUG
37017 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
37018 #endif
37019
37020 DEFVAR_LISP ("truncate-partial-width-windows",
37021 Vtruncate_partial_width_windows,
37022 doc:
37023
37024
37025
37026
37027
37028
37029
37030
37031
37032
37033
37034
37035
37036
37037
37038 );
37039 Vtruncate_partial_width_windows = make_fixnum (50);
37040
37041 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
37042
37043
37044
37045
37046
37047
37048
37049
37050
37051
37052
37053
37054
37055 );
37056 word_wrap_by_category = false;
37057
37058 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
37059 doc:
37060
37061 );
37062 Vline_number_display_limit = Qnil;
37063
37064 DEFVAR_INT ("line-number-display-limit-width",
37065 line_number_display_limit_width,
37066 doc:
37067
37068 );
37069 line_number_display_limit_width = 200;
37070
37071 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
37072 doc:
37073
37074 );
37075 highlight_nonselected_windows = false;
37076
37077 DEFVAR_BOOL ("multiple-frames", multiple_frames,
37078 doc:
37079
37080
37081 );
37082
37083 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
37084 doc:
37085
37086
37087
37088
37089 );
37090
37091 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
37092 doc:
37093
37094
37095
37096
37097
37098 );
37099
37100
37101 Lisp_Object icon_title_name_format
37102 = pure_list (empty_unibyte_string,
37103 build_pure_c_string ("%b - GNU Emacs at "),
37104 intern_c_string ("system-name"));
37105 Vicon_title_format
37106 = Vframe_title_format
37107 = pure_list (intern_c_string ("multiple-frames"),
37108 build_pure_c_string ("%b"),
37109 icon_title_name_format);
37110
37111 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
37112 doc:
37113
37114 );
37115 Vmessage_log_max = make_fixnum (1000);
37116
37117 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
37118 doc:
37119
37120
37121
37122
37123
37124
37125
37126
37127
37128
37129
37130
37131
37132 );
37133 Vwindow_scroll_functions = Qnil;
37134
37135 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
37136 doc:
37137
37138
37139
37140
37141
37142
37143
37144
37145
37146
37147
37148
37149
37150
37151
37152
37153
37154 );
37155 Vmouse_autoselect_window = Qnil;
37156
37157 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
37158 doc:
37159
37160
37161
37162
37163 );
37164 Vauto_resize_tab_bars = Qt;
37165
37166 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
37167 doc: );
37168 auto_raise_tab_bar_buttons_p = true;
37169
37170 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
37171 doc:
37172
37173
37174
37175
37176 );
37177 Vauto_resize_tool_bars = Qt;
37178
37179 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
37180 doc: );
37181 auto_raise_tool_bar_buttons_p = true;
37182
37183 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
37184 doc:
37185
37186
37187
37188
37189 );
37190 Vmake_cursor_line_fully_visible = Qt;
37191 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
37192
37193 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
37194 doc: );
37195 make_window_start_visible = false;
37196 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
37197 Fmake_variable_buffer_local (Qmake_window_start_visible);
37198
37199 DEFSYM (Qclose_tab, "close-tab");
37200 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
37201 doc:
37202
37203
37204
37205 );
37206 Vtab_bar_border = Qinternal_border_width;
37207
37208 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
37209 doc:
37210
37211
37212
37213 );
37214 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
37215
37216 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
37217 doc: );
37218 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
37219
37220 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
37221 doc:
37222
37223
37224
37225 );
37226 Vtool_bar_border = Qinternal_border_width;
37227
37228 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
37229 doc:
37230
37231
37232
37233 );
37234 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
37235
37236 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
37237 doc: );
37238 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
37239
37240 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
37241 doc:
37242
37243
37244
37245
37246
37247
37248
37249
37250 );
37251 Vtool_bar_style = Qnil;
37252
37253 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
37254 doc:
37255
37256 );
37257 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
37258
37259 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
37260 doc:
37261
37262
37263
37264
37265
37266
37267
37268
37269 );
37270 Vfontification_functions = Qnil;
37271 Fmake_variable_buffer_local (Qfontification_functions);
37272
37273 DEFVAR_BOOL ("unibyte-display-via-language-environment",
37274 unibyte_display_via_language_environment,
37275 doc:
37276
37277
37278
37279
37280
37281
37282 );
37283 unibyte_display_via_language_environment = false;
37284
37285 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
37286 doc:
37287
37288
37289
37290 );
37291 Vmax_mini_window_height = make_float (0.25);
37292
37293 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
37294 doc:
37295
37296
37297
37298
37299
37300
37301
37302
37303 );
37304
37305
37306
37307
37308
37309 Vresize_mini_windows = Qnil;
37310
37311 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
37312 doc:
37313
37314
37315
37316
37317
37318
37319
37320 );
37321 Vblink_cursor_alist = Qnil;
37322
37323 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
37324 doc:
37325
37326
37327
37328 );
37329 automatic_hscrolling = Qt;
37330 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
37331 DEFSYM (Qcurrent_line, "current-line");
37332
37333 DEFVAR_INT ("hscroll-margin", hscroll_margin,
37334 doc:
37335 );
37336 hscroll_margin = 5;
37337
37338 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37339 doc:
37340
37341
37342
37343
37344
37345
37346
37347
37348
37349
37350
37351
37352
37353 );
37354 Vhscroll_step = make_fixnum (0);
37355
37356 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37357 doc:
37358 );
37359 message_truncate_lines = false;
37360
37361 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37362 doc:
37363
37364
37365 );
37366 Vmenu_bar_update_hook = Qnil;
37367
37368 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37369 doc:
37370 );
37371 Vmenu_updating_frame = Qnil;
37372
37373 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37374 doc: );
37375 inhibit_menubar_update = false;
37376
37377 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37378 doc:
37379
37380
37381
37382
37383
37384
37385 );
37386 Vwrap_prefix = Qnil;
37387 DEFSYM (Qwrap_prefix, "wrap-prefix");
37388 Fmake_variable_buffer_local (Qwrap_prefix);
37389
37390 DEFVAR_LISP ("line-prefix", Vline_prefix,
37391 doc:
37392
37393
37394
37395
37396
37397
37398 );
37399 Vline_prefix = Qnil;
37400 DEFSYM (Qline_prefix, "line-prefix");
37401 Fmake_variable_buffer_local (Qline_prefix);
37402
37403 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37404 doc:
37405
37406
37407
37408
37409
37410
37411
37412
37413
37414
37415
37416
37417
37418
37419
37420
37421
37422
37423
37424
37425
37426
37427 );
37428 Vdisplay_line_numbers = Qnil;
37429 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37430 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37431 DEFSYM (Qrelative, "relative");
37432 DEFSYM (Qvisual, "visual");
37433
37434 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37435 doc:
37436
37437
37438
37439 );
37440 Vdisplay_line_numbers_width = Qnil;
37441 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37442 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37443
37444 DEFVAR_LISP ("display-line-numbers-current-absolute",
37445 Vdisplay_line_numbers_current_absolute,
37446 doc:
37447
37448 );
37449 Vdisplay_line_numbers_current_absolute = Qt;
37450
37451 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37452 doc: );
37453 display_line_numbers_widen = false;
37454 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37455 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37456
37457 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37458 doc:
37459
37460
37461 );
37462 display_line_numbers_offset = 0;
37463 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37464 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37465
37466 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37467 doc:
37468
37469
37470 );
37471 display_fill_column_indicator = false;
37472 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37473 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37474
37475 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37476 doc:
37477
37478
37479
37480 );
37481 Vdisplay_fill_column_indicator_column = Qt;
37482 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37483 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37484
37485 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37486 doc:
37487
37488
37489 );
37490 Vdisplay_fill_column_indicator_character = Qnil;
37491 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37492 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37493
37494 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37495 doc:
37496
37497
37498 );
37499 display_line_numbers_major_tick = 0;
37500
37501 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37502 doc:
37503
37504
37505 );
37506 display_line_numbers_minor_tick = 0;
37507
37508 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37509 doc: );
37510 inhibit_eval_during_redisplay = false;
37511
37512 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37513 doc: );
37514 inhibit_free_realized_faces = false;
37515
37516 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37517 doc:
37518
37519 );
37520 inhibit_bidi_mirroring = false;
37521
37522 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37523 doc:
37524
37525
37526
37527 );
37528 bidi_inhibit_bpa = false;
37529
37530 #ifdef GLYPH_DEBUG
37531 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37532 doc: );
37533 inhibit_try_window_id = false;
37534
37535 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37536 doc: );
37537 inhibit_try_window_reusing = false;
37538
37539 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37540 doc: );
37541 inhibit_try_cursor_movement = false;
37542 #endif
37543
37544 DEFVAR_INT ("overline-margin", overline_margin,
37545 doc:
37546
37547 );
37548 overline_margin = 2;
37549
37550 DEFVAR_INT ("underline-minimum-offset",
37551 underline_minimum_offset,
37552 doc:
37553
37554
37555
37556 );
37557 underline_minimum_offset = 1;
37558 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37559
37560 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37561 doc:
37562
37563 );
37564 display_hourglass_p = true;
37565
37566 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37567 doc: );
37568 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37569
37570 #ifdef HAVE_WINDOW_SYSTEM
37571 hourglass_atimer = NULL;
37572 hourglass_shown_p = false;
37573 #endif
37574
37575
37576 DEFSYM (Qglyphless_char, "glyphless-char");
37577
37578
37579 DEFSYM (Qhex_code, "hex-code");
37580 DEFSYM (Qempty_box, "empty-box");
37581 DEFSYM (Qthin_space, "thin-space");
37582 DEFSYM (Qzero_width, "zero-width");
37583
37584 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37585 doc:
37586
37587
37588 );
37589 Vpre_redisplay_function = intern ("ignore");
37590
37591
37592 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37593 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37594
37595 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37596 doc:
37597
37598
37599
37600
37601
37602
37603
37604
37605
37606
37607
37608
37609
37610
37611
37612
37613
37614
37615
37616
37617
37618
37619
37620 );
37621 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37622 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37623 Qempty_box);
37624
37625 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37626 doc: );
37627 Vdebug_on_message = Qnil;
37628
37629 DEFVAR_LISP ("set-message-function", Vset_message_function,
37630 doc:
37631
37632
37633
37634
37635
37636
37637
37638
37639
37640 );
37641 Vset_message_function = Qnil;
37642
37643 DEFSYM (Qdont_clear_message, "dont-clear-message");
37644 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37645 doc:
37646
37647
37648
37649
37650
37651
37652
37653
37654
37655
37656 );
37657 Vclear_message_function = Qnil;
37658
37659 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37660 doc:
37661 );
37662 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37663
37664 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37665 doc:
37666 );
37667 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37668
37669 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37670 doc: );
37671
37672
37673 redisplay__inhibit_bidi = true;
37674
37675 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37676 doc:
37677
37678 );
37679 display_raw_bytes_as_hex = false;
37680
37681 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37682 doc:
37683
37684 );
37685 mouse_fine_grained_tracking = false;
37686
37687 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37688 doc: );
37689 tab_bar__dragging_in_progress = false;
37690
37691 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37692 doc:
37693
37694
37695
37696 );
37697 redisplay_skip_initial_frame = true;
37698
37699 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37700 redisplay_skip_fontification_on_input,
37701 doc:
37702
37703
37704
37705
37706
37707
37708
37709 );
37710 redisplay_skip_fontification_on_input = false;
37711
37712 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37713 redisplay_adhoc_scroll_in_resize_mini_windows,
37714 doc:
37715
37716 );
37717
37718 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37719
37720 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37721 doc:
37722
37723 );
37724 composition_break_at_point = false;
37725
37726 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37727 doc:
37728
37729
37730
37731
37732
37733
37734
37735
37736
37737
37738
37739 );
37740 max_redisplay_ticks = 0;
37741 }
37742
37743
37744
37745
37746 void
37747 init_xdisp (void)
37748 {
37749 CHARPOS (this_line_start_pos) = 0;
37750
37751 echo_area_window = minibuf_window;
37752
37753 if (!noninteractive)
37754 {
37755 struct window *m = XWINDOW (minibuf_window);
37756 Lisp_Object frame = m->frame;
37757 struct frame *f = XFRAME (frame);
37758 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37759 struct window *r = XWINDOW (root);
37760 int i;
37761
37762 r->top_line = FRAME_TOP_MARGIN (f);
37763 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37764 r->total_cols = FRAME_COLS (f);
37765 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37766 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_MARGINS (f);
37767 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37768
37769 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37770 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37771 m->total_cols = FRAME_COLS (f);
37772 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37773 m->total_lines = 1;
37774 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37775
37776 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37777 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37778 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37779
37780
37781 for (i = 0; i < 3; ++i)
37782 default_invis_vector[i] = make_fixnum ('.');
37783 }
37784
37785 {
37786
37787
37788 int size = 100;
37789 mode_line_noprop_buf = xmalloc (size);
37790 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37791 mode_line_noprop_ptr = mode_line_noprop_buf;
37792 mode_line_target = MODE_LINE_DISPLAY;
37793 }
37794
37795 help_echo_showing_p = false;
37796 }
37797
37798 #ifdef HAVE_WINDOW_SYSTEM
37799
37800
37801
37802
37803
37804 static void
37805 show_hourglass (struct atimer *timer)
37806 {
37807
37808
37809
37810 hourglass_atimer = NULL;
37811
37812 if (!hourglass_shown_p)
37813 {
37814 Lisp_Object tail, frame;
37815
37816 block_input ();
37817
37818 FOR_EACH_FRAME (tail, frame)
37819 {
37820 struct frame *f = XFRAME (frame);
37821
37822 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37823 && FRAME_RIF (f)->show_hourglass)
37824 FRAME_RIF (f)->show_hourglass (f);
37825 }
37826
37827 hourglass_shown_p = true;
37828 unblock_input ();
37829 }
37830 }
37831
37832
37833
37834 void
37835 start_hourglass (void)
37836 {
37837 struct timespec delay;
37838
37839 cancel_hourglass ();
37840
37841 if (FIXNUMP (Vhourglass_delay)
37842 && XFIXNUM (Vhourglass_delay) > 0)
37843 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37844 TYPE_MAXIMUM (time_t)),
37845 0);
37846 else if (FLOATP (Vhourglass_delay)
37847 && XFLOAT_DATA (Vhourglass_delay) > 0)
37848 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37849 else
37850 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37851
37852 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37853 show_hourglass, NULL);
37854 }
37855
37856
37857
37858
37859 void
37860 cancel_hourglass (void)
37861 {
37862 if (hourglass_atimer)
37863 {
37864 cancel_atimer (hourglass_atimer);
37865 hourglass_atimer = NULL;
37866 }
37867
37868 if (hourglass_shown_p)
37869 {
37870 Lisp_Object tail, frame;
37871
37872 block_input ();
37873
37874 FOR_EACH_FRAME (tail, frame)
37875 {
37876 struct frame *f = XFRAME (frame);
37877
37878 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37879 && FRAME_RIF (f)->hide_hourglass)
37880 FRAME_RIF (f)->hide_hourglass (f);
37881 #ifdef HAVE_NTGUI
37882
37883 else if (!FRAME_W32_P (f))
37884 w32_arrow_cursor ();
37885 #endif
37886 }
37887
37888 hourglass_shown_p = false;
37889 unblock_input ();
37890 }
37891 }
37892
37893
37894
37895
37896
37897
37898
37899
37900 static int
37901 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37902 struct window *w,
37903 struct face *original_face,
37904 struct face *mouse_face)
37905 {
37906 int sum = 0;
37907
37908 bool do_left_box_p = g->left_box_line_p;
37909 bool do_right_box_p = g->right_box_line_p;
37910
37911
37912
37913 if (g->type == IMAGE_GLYPH)
37914 {
37915 if (!row->reversed_p)
37916 {
37917 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37918 g->u.img_id);
37919 do_left_box_p = g->left_box_line_p &&
37920 g->slice.img.x == 0;
37921 do_right_box_p = g->right_box_line_p &&
37922 g->slice.img.x + g->slice.img.width == img->width;
37923 }
37924 else
37925 {
37926 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37927 g->u.img_id);
37928 do_left_box_p = g->left_box_line_p &&
37929 g->slice.img.x + g->slice.img.width == img->width;
37930 do_right_box_p = g->right_box_line_p &&
37931 g->slice.img.x == 0;
37932 }
37933 }
37934
37935
37936 if (do_left_box_p)
37937 sum -= max (0, original_face->box_vertical_line_width);
37938
37939
37940 if (do_right_box_p)
37941 sum -= max (0, original_face->box_vertical_line_width);
37942
37943 if (g->left_box_line_p)
37944 sum += max (0, mouse_face->box_vertical_line_width);
37945 if (g->right_box_line_p)
37946 sum += max (0, mouse_face->box_vertical_line_width);
37947
37948 return sum;
37949 }
37950
37951
37952
37953
37954
37955
37956
37957
37958
37959 static void
37960 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37961 int *offset)
37962 {
37963 int sum = 0;
37964
37965 if (row->mode_line_p)
37966 return;
37967
37968 block_input ();
37969
37970 struct frame *f = WINDOW_XFRAME (w);
37971 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37972 struct glyph *start, *end;
37973 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37974 int hpos = w->phys_cursor.hpos;
37975 end = &row->glyphs[TEXT_AREA][hpos];
37976
37977 if (!row->reversed_p)
37978 {
37979 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37980 hlinfo->mouse_face_beg_row)
37981 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37982 else
37983 start = row->glyphs[TEXT_AREA];
37984 }
37985 else
37986 {
37987 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37988 hlinfo->mouse_face_end_row)
37989 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37990 else
37991 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37992 }
37993
37994
37995
37996
37997 for ( ; row->reversed_p ? start > end : start < end;
37998 row->reversed_p ? --start : ++start)
37999 sum += adjust_glyph_width_for_mouse_face (start, row, w,
38000 FACE_FROM_ID (f, start->face_id),
38001 mouse_face);
38002
38003 if (row->reversed_p)
38004 sum = -sum;
38005
38006 *offset = sum;
38007
38008 unblock_input ();
38009 }
38010 #endif